Exemplo n.º 1
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *local_port = NULL;
    char *local_addr = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    srand(time(NULL));

    int remote_num = 0;
    ss_addr_t remote_addr[MAX_REMOTE_NUM];
    char *remote_port = NULL;

    int option_index = 0;
    static struct option long_options[] =
    {
        { "fast-open", no_argument,       0, 0 },
        { "acl",       required_argument, 0, 0 },
        { 0,           0,                 0, 0 }
    };

    opterr = 0;

    USE_TTY();

#ifdef ANDROID
    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvVA",
                            long_options, &option_index)) != -1) {
#else
    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvA",
                            long_options, &option_index)) != -1) {
#endif
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGI("initialize acl...");
                acl = !init_acl(optarg);
            }
            break;
        case 's':
            if (remote_num < MAX_REMOTE_NUM) {
                remote_addr[remote_num].host = optarg;
                remote_addr[remote_num++].port = NULL;
            }
            break;
        case 'p':
            remote_port = optarg;
            break;
        case 'l':
            local_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'i':
            iface = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'A':
            auth = 1;
            break;
#ifdef ANDROID
        case 'V':
            vpn = 1;
            break;
#endif
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }
    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (remote_num == 0) {
            remote_num = conf->remote_num;
            for (i = 0; i < remote_num; i++) {
                remote_addr[i] = conf->remote_addr[i];
            }
        }
        if (remote_port == NULL) {
            remote_port = conf->remote_port;
        }
        if (local_addr == NULL) {
            local_addr = conf->local_addr;
        }
        if (local_port == NULL) {
            local_port = conf->local_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
    }

    if (remote_num == 0 || remote_port == NULL ||
        local_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (timeout == NULL) {
        timeout = "60";
    }

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

    if (auth) {
        LOGI("onetime authentication enabled");
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // Setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // Setup proxy context
    struct listen_ctx listen_ctx;
    listen_ctx.remote_num = remote_num;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *) * remote_num);
    for (i = 0; i < remote_num; i++) {
        char *host = remote_addr[i].host;
        char *port = remote_addr[i].port == NULL ? remote_port :
            remote_addr[i].port;
        struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.iface = iface;
    listen_ctx.method = m;

    struct ev_loop *loop = EV_DEFAULT;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port);
    if (listenfd < 0) {
        FATAL("bind() error");
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        FATAL("listen() error");
    }
    setnonblocking(listenfd);

    listen_ctx.fd = listenfd;

    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("udprelay enabled");
        init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), m, auth, listen_ctx.timeout, iface);
    }

    LOGI("listening at %s:%s", local_addr, local_port);

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);

    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    for (i = 0; i < remote_num; i++) {
        free(listen_ctx.remote_addr[i]);
    }
    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}

#else

int start_ss_local_server(profile_t profile)
{
    srand(time(NULL));

    char *remote_host = profile.remote_host;
    char *local_addr = profile.local_addr;
    char *method = profile.method;
    char *password = profile.password;
    char *log = profile.log;
    int remote_port = profile.remote_port;
    int local_port = profile.local_port;
    int timeout = profile.timeout;

    mode = profile.mode;
    fast_open = profile.fast_open;
    verbose = profile.verbose;

    char local_port_str[16];
    char remote_port_str[16];
    sprintf(local_port_str, "%d", local_port);
    sprintf(remote_port_str, "%d", remote_port);

    USE_LOGFILE(log);

    if (profile.acl != NULL) {
        acl = !init_acl(profile.acl);
    }

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // Setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
    memset(storage, 0, sizeof(struct sockaddr_storage));
    if (get_sockaddr(remote_host, remote_port_str, storage, 1) == -1) {
        return -1;
    }

    // Setup proxy context
    struct ev_loop *loop = EV_DEFAULT;
    struct listen_ctx listen_ctx;

    listen_ctx.remote_num = 1;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *));
    listen_ctx.remote_addr[0] = (struct sockaddr *)storage;
    listen_ctx.timeout = timeout;
    listen_ctx.method = m;
    listen_ctx.iface = NULL;

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port_str);
    if (listenfd < 0) {
        ERROR("bind()");
        return -1;
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        ERROR("listen()");
        return -1;
    }
    setnonblocking(listenfd);

    listen_ctx.fd = listenfd;

    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("udprelay enabled");
        struct sockaddr *addr = (struct sockaddr *)storage;
        init_udprelay(local_addr, local_port_str, addr,
                      get_sockaddr_len(addr), m, auth, timeout, NULL);
    }

    LOGI("listening at %s:%s", local_addr, local_port_str);

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    ev_io_stop(loop, &listen_ctx.io);
    free_connections(loop);
    close(listen_ctx.fd);

    free(listen_ctx.remote_addr);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    // cannot reach here
    return 0;
}
Exemplo n.º 2
0
int
main(int argc, char **argv) {
    const char *config_file = "/etc/sniproxy.conf";
    int background_flag = 1;
    rlim_t max_nofiles = 65536;
    int opt;

    while ((opt = getopt(argc, argv, "fc:n:V")) != -1) {
        switch (opt) {
            case 'c':
                config_file = optarg;
                break;
            case 'f': /* foreground */
                background_flag = 0;
                break;
            case 'n':
                max_nofiles = strtoul(optarg, NULL, 10);
                break;
            case 'V':
                printf("sniproxy %s\n", sniproxy_version);
                return EXIT_SUCCESS;
            default:
                usage();
                return EXIT_FAILURE;
        }
    }

    config = init_config(config_file, EV_DEFAULT);
    if (config == NULL) {
        fprintf(stderr, "Unable to load %s\n", config_file);
        usage();
        return EXIT_FAILURE;
    }

    /* ignore SIGPIPE, or it will kill us */
    signal(SIGPIPE, SIG_IGN);

    if (background_flag) {
        if (config->pidfile != NULL)
            remove(config->pidfile);

        daemonize();


        if (config->pidfile != NULL)
            write_pidfile(config->pidfile, getpid());
    }

    start_binder();

    set_limits(max_nofiles);

    init_listeners(&config->listeners, &config->tables, EV_DEFAULT);

    /* Drop permissions only when we can */
    drop_perms(config->user ? config->user : default_username, config->group);

    ev_signal_init(&sighup_watcher, signal_cb, SIGHUP);
    ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1);
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sighup_watcher);
    ev_signal_start(EV_DEFAULT, &sigusr1_watcher);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    resolv_init(EV_DEFAULT, config->resolver.nameservers,
            config->resolver.search, config->resolver.mode);

    init_connections();

    ev_run(EV_DEFAULT, 0);

    free_connections(EV_DEFAULT);
    resolv_shutdown(EV_DEFAULT);

    free_config(config, EV_DEFAULT);

    stop_binder();

    return 0;
}
Exemplo n.º 3
0
int
main(int argc, char **argv)
{
    srand(time(NULL));

    int i, c;
    int pid_flags    = 0;
    int mptcp        = 0;
    int mtu          = 0;
    char *user       = NULL;
    char *local_port = NULL;
    char *local_addr = NULL;
    char *password   = NULL;
    char *key        = NULL;
    char *timeout    = NULL;
    char *method     = NULL;
    char *pid_path   = NULL;
    char *conf_path  = NULL;

    char *plugin      = NULL;
    char *plugin_opts = NULL;
    char *plugin_host = NULL;
    char *plugin_port = NULL;
    char tmp_port[8];

    int remote_num = 0;
    ss_addr_t remote_addr[MAX_REMOTE_NUM];
    char *remote_port = NULL;

    static struct option long_options[] = {
        { "fast-open",   no_argument,       NULL, GETOPT_VAL_FAST_OPEN },
        { "mtu",         required_argument, NULL, GETOPT_VAL_MTU },
        { "mptcp",       no_argument,       NULL, GETOPT_VAL_MPTCP },
        { "plugin",      required_argument, NULL, GETOPT_VAL_PLUGIN },
        { "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
        { "reuse-port",  no_argument,       NULL, GETOPT_VAL_REUSE_PORT },
        { "password",    required_argument, NULL, GETOPT_VAL_PASSWORD },
        { "key",         required_argument, NULL, GETOPT_VAL_KEY },
        { "help",        no_argument,       NULL, GETOPT_VAL_HELP },
        { NULL,          0,                 NULL, 0 }
    };

    opterr = 0;

    USE_TTY();

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6A",
                            long_options, NULL)) != -1) {
        switch (c) {
        case GETOPT_VAL_FAST_OPEN:
            fast_open = 1;
            break;
        case GETOPT_VAL_MTU:
            mtu = atoi(optarg);
            LOGI("set MTU to %d", mtu);
            break;
        case GETOPT_VAL_MPTCP:
            mptcp = 1;
            LOGI("enable multipath TCP");
            break;
        case GETOPT_VAL_PLUGIN:
            plugin = optarg;
            break;
        case GETOPT_VAL_PLUGIN_OPTS:
            plugin_opts = optarg;
            break;
        case GETOPT_VAL_KEY:
            key = optarg;
            break;
        case GETOPT_VAL_REUSE_PORT:
            reuse_port = 1;
            break;
        case 's':
            if (remote_num < MAX_REMOTE_NUM) {
                remote_addr[remote_num].host   = optarg;
                remote_addr[remote_num++].port = NULL;
            }
            break;
        case 'p':
            remote_port = optarg;
            break;
        case 'l':
            local_port = optarg;
            break;
        case GETOPT_VAL_PASSWORD:
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path  = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'b':
            local_addr = optarg;
            break;
        case 'a':
            user = optarg;
            break;
#ifdef HAVE_SETRLIMIT
        case 'n':
            nofile = atoi(optarg);
            break;
#endif
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 1;
            break;
        case GETOPT_VAL_HELP:
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        case '6':
            ipv6first = 1;
            break;
        case 'A':
            FATAL("One time auth has been deprecated. Try AEAD ciphers instead.");
            break;
        case '?':
            // The option character is not recognized.
            LOGE("Unrecognized option: %s", optarg);
            opterr = 1;
            break;
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }

    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (remote_num == 0) {
            remote_num = conf->remote_num;
            for (i = 0; i < remote_num; i++)
                remote_addr[i] = conf->remote_addr[i];
        }
        if (remote_port == NULL) {
            remote_port = conf->remote_port;
        }
        if (local_addr == NULL) {
            local_addr = conf->local_addr;
        }
        if (local_port == NULL) {
            local_port = conf->local_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (key == NULL) {
            key = conf->key;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (user == NULL) {
            user = conf->user;
        }
        if (plugin == NULL) {
            plugin = conf->plugin;
        }
        if (plugin_opts == NULL) {
            plugin_opts = conf->plugin_opts;
        }
        if (mode == TCP_ONLY) {
            mode = conf->mode;
        }
        if (mtu == 0) {
            mtu = conf->mtu;
        }
        if (mptcp == 0) {
            mptcp = conf->mptcp;
        }
        if (reuse_port == 0) {
            reuse_port = conf->reuse_port;
        }
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
#endif
    }

    if (remote_num == 0 || remote_port == NULL || local_port == NULL
            || (password == NULL && key == NULL)) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (plugin != NULL) {
        uint16_t port = get_local_port();
        if (port == 0) {
            FATAL("failed to find a free port");
        }
        snprintf(tmp_port, 8, "%d", port);
        plugin_host = "127.0.0.1";
        plugin_port = tmp_port;

        LOGI("plugin \"%s\" enabled", plugin);
    }

    if (method == NULL) {
        method = "rc4-md5";
    }

    if (timeout == NULL) {
        timeout = "600";
    }

#ifdef HAVE_SETRLIMIT
    /*
     * no need to check the return value here since we will show
     * the user an error message if setrlimit(2) fails
     */
    if (nofile > 1024) {
        if (verbose) {
            LOGI("setting NOFILE to %d", nofile);
        }
        set_nofile(nofile);
    }
#endif

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }


    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
        fast_open = 0;
#endif
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (ipv6first) {
        LOGI("resolving hostname to IPv6 address first");
    }

    if (plugin != NULL) {
        int len = 0;
        size_t buf_size = 256 * remote_num;
        char *remote_str = ss_malloc(buf_size);

        snprintf(remote_str, buf_size, "%s", remote_addr[0].host);
        for (int i = 1; i < remote_num; i++) {
            snprintf(remote_str + len, buf_size - len, "|%s", remote_addr[i].host);
            len = strlen(remote_str);
        }
        int err = start_plugin(plugin, plugin_opts, remote_str,
                remote_port, plugin_host, plugin_port, MODE_CLIENT);
        if (err) {
            FATAL("failed to start the plugin");
        }
    }

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);
    ev_signal_start(EV_DEFAULT, &sigchld_watcher);

    // Setup keys
    LOGI("initializing ciphers... %s", method);
    crypto = crypto_init(password, key, method);
    if (crypto == NULL)
        FATAL("failed to initialize ciphers");

    // Setup proxy context
    struct listen_ctx listen_ctx;
    memset(&listen_ctx, 0, sizeof(struct listen_ctx));
    listen_ctx.remote_num  = remote_num;
    listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num);
    memset(listen_ctx.remote_addr, 0, sizeof(struct sockaddr *) * remote_num);
    for (i = 0; i < remote_num; i++) {
        char *host = remote_addr[i].host;
        char *port = remote_addr[i].port == NULL ? remote_port :
                     remote_addr[i].port;
        if (plugin != NULL) {
            host = plugin_host;
            port = plugin_port;
        }
        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        listen_ctx.remote_addr[i] = (struct sockaddr *)storage;

        if (plugin != NULL) break;
    }
    listen_ctx.timeout = atoi(timeout);
    listen_ctx.mptcp   = mptcp;

    struct ev_loop *loop = EV_DEFAULT;

    if (mode != UDP_ONLY) {
        // Setup socket
        int listenfd;
        listenfd = create_and_bind(local_addr, local_port);
        if (listenfd == -1) {
            FATAL("bind() error");
        }
        if (listen(listenfd, SOMAXCONN) == -1) {
            FATAL("listen() error");
        }
        setnonblocking(listenfd);

        listen_ctx.fd = listenfd;

        ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
        ev_io_start(loop, &listen_ctx.io);
    }

    // Setup UDP
    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
        char *host = remote_addr[0].host;
        char *port = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;
        struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage));
        memset(storage, 0, sizeof(struct sockaddr_storage));
        if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) {
            FATAL("failed to resolve the provided hostname");
        }
        struct sockaddr *addr = (struct sockaddr *)storage;
        init_udprelay(local_addr, local_port, addr,
                      get_sockaddr_len(addr), mtu, crypto, listen_ctx.timeout, NULL);
    }

    if (mode == UDP_ONLY) {
        LOGI("TCP relay disabled");
    }

    LOGI("listening at %s:%s", local_addr, local_port);

    // setuid
    if (user != NULL && !run_as(user)) {
        FATAL("failed to switch user");
    }

    if (geteuid() == 0) {
        LOGI("running from root user");
    }

    ev_run(loop, 0);

    if (plugin != NULL) {
        stop_plugin();
    }

    return 0;
}
Exemplo n.º 4
0
int
main(int argc, char *argv[])
{
    struct hostent *server_host;
    char *server_host_str = "localhost";
    char *certificate_file = NULL;
    char *key_file = NULL;
    char *password_file = NULL;
    char *token_file = NULL;
    char *username = "******";
    int port = 64738;
    int ret;
    int development_mode = 0;

    int socket_fd;
    struct sockaddr_in server_addr;

    SSLRead socket_watcher;
    ev_io user_thread_watcher;
    ev_timer ping_watcher;
    ev_signal signal_watcher;
    ev_loop_main = EV_DEFAULT;

    /*
     * Lua initialization
     */
    lua = luaL_newstate();
    if (lua == NULL) {
        fprintf(stderr, "%s: could not initialize Lua\n", PIEPAN_NAME);
        return 1;
    }
    luaL_openlibs(lua);
    if (luaL_loadbuffer(lua, (const char *)src_piepan_impl_luac,
            src_piepan_impl_luac_len, "piepan_impl") != LUA_OK) {
        fprintf(stderr, "%s: could not load piepan implementation\n", PIEPAN_NAME);
        return 1;
    }
    lua_call(lua, 0, 0);

    lua_getglobal(lua, "piepan");
    lua_getfield(lua, -1, "internal");
    lua_getfield(lua, -1, "api");
    lua_pushcfunction(lua, api_init);
    lua_setfield(lua, -2, "apiInit");
    lua_settop(lua, 0);

    /*
     * Argument parsing
     */
    {
        int opt;
        int i;
        int show_help = 0;
        int show_version = 0;
        lua_getglobal(lua, "piepan");
        lua_getfield(lua, -1, "internal");
        lua_getfield(lua, -1, "events");
        lua_getfield(lua, -1, "onArgument");
        opterr = 0;
        while ((opt = getopt(argc, argv, "u:c:k:s:t:p:-:dhv")) != -1) {
            switch (opt) {
                case 'u':
                    username = optarg;
                    break;
                case 'c':
                    certificate_file = optarg;
                    if (key_file == NULL) {
                        key_file = certificate_file;
                    }
                    break;
                case 'k':
                    key_file = optarg;
                    break;
                case 's': {
                    char *port_str;
                    server_host_str = optarg;
                    port_str = strrchr(server_host_str, ':');
                    if (port_str != NULL) {
                        *port_str = '\0';
                        port = atoi(++port_str);
                    }
                    break;
                }
                case 't':
                    token_file = optarg;
                    break;
                case 'p':
                    password_file = optarg;
                    break;
                case '-': {
                    char *key = optarg;
                    char *value = strchr(key, '=');
                    if (key == value) {
                        break;
                    }
                    if (value != NULL) {
                        *value++ = 0;
                    }
                    lua_pushvalue(lua, -1);
                    lua_pushstring(lua, key);
                    lua_pushstring(lua, value);
                    lua_call(lua, 2, 0);
                    break;
                }
                case 'd':
                    development_mode = 1;
                    break;
                case 'h':
                    usage(stdout);
                    return 0;
                case 'v':
                    printf("%s %s (compiled on " __DATE__ " " __TIME__ ")\n",
                           PIEPAN_NAME, PIEPAN_VERSION);
                    return 0;
                default:
                    fprintf(stderr, "%s: unknown or incomplete option '%c'\n",
                            PIEPAN_NAME, optopt);
                    return 1;
            }
        }
        lua_settop(lua, 0);
    }

    /*
     * Load user scripts
     */
    {
        int i;
        lua_getglobal(lua, "piepan");
        lua_getfield(lua, -1, "internal");
        lua_getfield(lua, -1, "events");
        lua_getfield(lua, -1, "onLoadScript");
        for (i = optind; i < argc; i++) {
            lua_pushvalue(lua, -1);
            lua_pushstring(lua, argv[i]);
            if (development_mode) {
                lua_newuserdata(lua, sizeof(ScriptStat));
            } else {
                lua_pushnil(lua);
            }
            lua_call(lua, 2, 3);
            if (lua_toboolean(lua, -3)) {
                if (development_mode) {
                    ScriptStat *item = lua_touserdata(lua, -1);
                    item->lua = lua;
                    item->id = lua_tointeger(lua, -2);
                    item->filename = argv[i];
                    ev_stat_init(&item->ev, script_stat_event, item->filename, 0);
                    ev_stat_start(ev_loop_main, &item->ev);
                }
            } else {
                fprintf(stderr, "%s: %s\n", PIEPAN_NAME, lua_tostring(lua, -2));
            }
            lua_pop(lua, 3);
        }
        lua_settop(lua, 0);
    }

    /*
     * Initialize Opus
     */
    {
        OpusEncoder *encoder;
        int error;

        lua_getglobal(lua, "piepan");
        lua_getfield(lua, -1, "internal");
        lua_getfield(lua, -1, "opus");
        encoder = lua_newuserdata(lua, opus_encoder_get_size(1));
        lua_setfield(lua, -2, "encoder");

        error = opus_encoder_init(encoder, 48000, 1, OPUS_APPLICATION_AUDIO);
        if (error != OPUS_OK) {
            fprintf(stderr, "%s: could not initialize the Opus encoder: %s\n",
                    PIEPAN_NAME, opus_strerror(error));
            return 1;
        }
        opus_encoder_ctl(encoder, OPUS_SET_VBR(0));
        /* TODO: set this to the server's max bitrate */
        opus_encoder_ctl(encoder, OPUS_SET_BITRATE(40000));

        lua_settop(lua, 0);
    }

    /*
     * SSL initialization
     */
    SSL_library_init();

    ssl_context = SSL_CTX_new(SSLv23_client_method());
    if (ssl_context == NULL) {
        fprintf(stderr, "%s: could not create SSL context\n", PIEPAN_NAME);
        return 1;
    }

    if (certificate_file != NULL) {
        if (!SSL_CTX_use_certificate_chain_file(ssl_context, certificate_file) ||
                !SSL_CTX_use_PrivateKey_file(ssl_context, key_file,
                                                SSL_FILETYPE_PEM) ||
                !SSL_CTX_check_private_key(ssl_context)) {
            fprintf(stderr, "%s: could not load certificate and/or key file\n",
                    PIEPAN_NAME);
            return 1;
        }
    }

    /*
     * Socket initialization and connection
     */
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0) {
        fprintf(stderr, "%s: could not create socket\n", PIEPAN_NAME);
        return 1;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);

    server_host = gethostbyname(server_host_str);
    if (server_host == NULL || server_host->h_addr_list[0] == NULL ||
            server_host->h_addrtype != AF_INET) {
        fprintf(stderr, "%s: could not parse server address\n", PIEPAN_NAME);
        return 1;
    }
    memmove(&server_addr.sin_addr, server_host->h_addr_list[0],
            server_host->h_length);

    ret = connect(socket_fd, (struct sockaddr *) &server_addr,
                  sizeof(server_addr));
    if (ret != 0) {
        fprintf(stderr, "%s: could not connect to server\n", PIEPAN_NAME);
        return 1;
    }

    ssl = SSL_new(ssl_context);
    if (ssl == NULL) {
        fprintf(stderr, "%s: could not create SSL object\n", PIEPAN_NAME);
        return 1;
    }

    if (SSL_set_fd(ssl, socket_fd) == 0) {
        fprintf(stderr, "%s: could not set SSL file descriptor\n", PIEPAN_NAME);
        return 1;
    }

    if (SSL_connect(ssl) != 1) {
        fprintf(stderr, "%s: could not create secure connection\n", PIEPAN_NAME);
        return 1;
    }

    /*
     * User thread pipe
     */
    if (pipe(user_thread_pipe) != 0) {
        fprintf(stderr, "%s: could not create user thread pipe\n", PIEPAN_NAME);
        return 1;
    }

    /*
     * Trigger initial event
     */
    lua_getglobal(lua, "piepan");
    lua_getfield(lua, -1, "internal");
    lua_getfield(lua, -1, "initialize");
    lua_newtable(lua);
    lua_pushstring(lua, username);
    lua_setfield(lua, -2, "username");
    if (password_file != NULL) {
        lua_pushstring(lua, password_file);
        lua_setfield(lua, -2, "passwordFile");
    }
    if (token_file != NULL) {
        lua_pushstring(lua, token_file);
        lua_setfield(lua, -2, "tokenFile");
    }
    lua_pushlightuserdata(lua, lua);
    lua_setfield(lua, -2, "state");
    lua_call(lua, 1, 0);
    lua_settop(lua, 0);

    /*
     * Event loop
     */
    ev_signal_init(&signal_watcher, signal_event, SIGINT);
    ev_signal_start(ev_loop_main, &signal_watcher);

    ev_io_init(&socket_watcher.ev, socket_read_event, socket_fd, EV_READ);
    socket_watcher.lua = lua;
    socket_watcher.ssl = ssl;
    ev_io_start(ev_loop_main, &socket_watcher.ev);

    ev_io_init(&user_thread_watcher, user_thread_event, user_thread_pipe[0],
               EV_READ);
    ev_io_start(ev_loop_main, &user_thread_watcher);

    ev_timer_init(&ping_watcher, ping_event, PING_TIMEOUT, PING_TIMEOUT);
    ev_timer_start(ev_loop_main, &ping_watcher);

    ev_run(ev_loop_main, 0);

    /*
     * Cleanup
     */
    lua_getglobal(lua, "piepan");
    lua_getfield(lua, -1, "internal");
    lua_getfield(lua, -1, "events");
    lua_getfield(lua, -1, "onDisconnect");
    if (lua_isfunction(lua, -1)) {
        lua_newtable(lua);
        lua_call(lua, 1, 0);
    }

    SSL_shutdown(ssl); /* TODO:  sigpipe is triggered here if connection breaks */
    close(socket_fd);
    lua_close(lua);

    return 0;
}
Exemplo n.º 5
0
/**
 * @brief Main routine of the sysrepo daemon.
 */
int
main(int argc, char* argv[])
{
    sr_pd_ctx_t ctx = { 0, };
    pid_t parent_pid = 0;
    int pidfile_fd = -1;
    int c = 0;
    bool debug_mode = false;
    int log_level = -1;
    int rc = SR_ERR_OK;

    while ((c = getopt (argc, argv, "hvdDl:")) != -1) {
        switch (c) {
            case 'v':
                sr_pd_print_version();
                return 0;
                break;
            case 'd':
                debug_mode = true;
                break;
            case 'D':
                connect_options |= SR_CONN_DAEMON_START;
                break;
            case 'l':
                log_level = atoi(optarg);
                break;
            default:
                sr_pd_print_help();
                return 0;
        }
    }

    /* init logger */
    sr_logger_init("sysrepo-plugind");

    /* daemonize the process */
    parent_pid = sr_daemonize(debug_mode, log_level, SR_PLUGIN_DAEMON_PID_FILE, &pidfile_fd);

    SR_LOG_DBG_MSG("Sysrepo plugin daemon initialization started.");

    /* init the event loop */
    ctx.event_loop = ev_loop_new(EVFLAG_AUTO);

    /* init signal watchers */
    ev_signal_init(&ctx.signal_watcher[0], sr_pd_signal_cb, SIGTERM);
    ev_signal_start(ctx.event_loop, &ctx.signal_watcher[0]);
    ev_signal_init(&ctx.signal_watcher[1], sr_pd_signal_cb, SIGINT);
    ev_signal_start(ctx.event_loop, &ctx.signal_watcher[1]);

    /* init timers */
    ev_timer_init(&ctx.health_check_timer, sr_pd_health_check_timer_cb, SR_PLUGIN_HEALTH_CHECK_TIMEOUT,
            SR_PLUGIN_HEALTH_CHECK_TIMEOUT);
    ctx.health_check_timer.data = &ctx;
    ev_timer_init(&ctx.init_retry_timer, sr_pd_init_retry_timer_cb, SR_PLUGIN_INIT_RETRY_TIMEOUT, SR_PLUGIN_INIT_RETRY_TIMEOUT);
    ctx.init_retry_timer.data = &ctx;

    /* connect to sysrepo */
    rc = sr_connect("sysrepo-plugind", connect_options, &ctx.connection);
    CHECK_RC_LOG_GOTO(rc, cleanup, "Unable to connect to sysrepod: %s", sr_strerror(rc));

    /* start the session */
    rc = sr_session_start(ctx.connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &ctx.session);
    CHECK_RC_LOG_GOTO(rc, cleanup, "Unable to connect to sysrepo: %s", sr_strerror(rc));

    /* tell the parent process that we are okay */
    if (!debug_mode) {
        sr_daemonize_signal_success(parent_pid);
    }

    /* load the plugins */
    rc = sr_pd_load_plugins(&ctx);

    SR_LOG_INF_MSG("Sysrepo plugin daemon initialized successfully.");

    /* start health check timer */
    ev_timer_start(ctx.event_loop, &ctx.health_check_timer);

    /* run the event loop */
    ev_run(ctx.event_loop, 0);

    ev_loop_destroy(ctx.event_loop);

    /* check whether the session is still valid & reconnect if needed */
    sr_pd_session_check(&ctx);

cleanup:
    sr_pd_cleanup_plugins(&ctx);

    if (NULL != ctx.session) {
        sr_session_stop(ctx.session);
    }
    if (NULL != ctx.connection) {
        sr_disconnect(ctx.connection);
    }

    SR_LOG_INF_MSG("Sysrepo plugin daemon terminated.");
    sr_logger_cleanup();

    unlink(SR_PLUGIN_DAEMON_PID_FILE);
    if (-1 != pidfile_fd) {
        close(pidfile_fd);
    }

    exit((SR_ERR_OK == rc) ? EXIT_SUCCESS : EXIT_FAILURE);
}
Exemplo n.º 6
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    int server_num = 0;
    const char *server_host[MAX_REMOTE_NUM];

    char * nameservers[MAX_DNS_NUM + 1];
    int nameserver_num = 0;

    int option_index = 0;
    static struct option long_options[] =
    {
        { "fast-open",          no_argument,       0, 0 },
        { "acl",                required_argument, 0, 0 },
        { "manager-address",    required_argument, 0, 0 },
        { 0,                    0,                 0, 0 }
    };

    opterr = 0;

    USE_TTY();

    while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:i:d:a:uUvA",
                            long_options, &option_index)) != -1) {
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGI("initialize acl...");
                acl = !init_acl(optarg);
            } else if (option_index == 2) {
                manager_address = optarg;
            }
            break;
        case 's':
            if (server_num < MAX_REMOTE_NUM) {
                server_host[server_num++] = optarg;
            }
            break;
        case 'p':
            server_port = optarg;
            break;
        case 'k':
            password = optarg;
            break;
        case 'f':
            pid_flags = 1;
            pid_path = optarg;
            break;
        case 't':
            timeout = optarg;
            break;
        case 'm':
            method = optarg;
            break;
        case 'c':
            conf_path = optarg;
            break;
        case 'i':
            iface = optarg;
            break;
        case 'd':
            if (nameserver_num < MAX_DNS_NUM) {
                nameservers[nameserver_num++] = optarg;
            }
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'A':
            auth = 1;
            break;
        }
    }

    if (opterr) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (argc == 1) {
        if (conf_path == NULL) {
            conf_path = DEFAULT_CONF_PATH;
        }
    }

    if (conf_path != NULL) {
        jconf_t *conf = read_jconf(conf_path);
        if (server_num == 0) {
            server_num = conf->remote_num;
            for (i = 0; i < server_num; i++) {
                server_host[i] = conf->remote_addr[i].host;
            }
        }
        if (server_port == NULL) {
            server_port = conf->remote_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
        if (auth == 0) {
            auth = conf->auth;
        }
#ifdef TCP_FASTOPEN
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#endif
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
        if (conf->nameserver != NULL) {
            nameservers[nameserver_num++] = conf->nameserver;
        }
    }

    if (server_num == 0) {
        server_host[server_num++] = NULL;
    }

    if (server_num == 0 || server_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (method == NULL) {
        method = "table";
    }

    if (timeout == NULL) {
        timeout = "60";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

    if (auth) {
        LOGI("onetime authentication enabled");
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // setup udns
    if (nameserver_num == 0) {
#ifdef __MINGW32__
        nameservers[nameserver_num++] = "8.8.8.8";
        resolv_init(loop, nameservers, nameserver_num);
#else
        resolv_init(loop, NULL, 0);
#endif
    } else {
        resolv_init(loop, nameservers, nameserver_num);
    }

    for (int i = 0; i < nameserver_num; i++) {
        LOGI("using nameserver: %s", nameservers[i]);
    }

    // inilitialize listen context
    struct listen_ctx listen_ctx_list[server_num];

    // bind to each interface
    while (server_num > 0) {
        int index = --server_num;
        const char * host = server_host[index];

        if (mode != UDP_ONLY) {
            // Bind to port
            int listenfd;
            listenfd = create_and_bind(host, server_port);
            if (listenfd < 0) {
                FATAL("bind() error");
            }
            if (listen(listenfd, SSMAXCONN) == -1) {
                FATAL("listen() error");
            }
            setnonblocking(listenfd);
            struct listen_ctx *listen_ctx = &listen_ctx_list[index];

            // Setup proxy context
            listen_ctx->timeout = atoi(timeout);
            listen_ctx->fd = listenfd;
            listen_ctx->method = m;
            listen_ctx->iface = iface;
            listen_ctx->loop = loop;

            ev_io_init(&listen_ctx->io, accept_cb, listenfd, EV_READ);
            ev_io_start(loop, &listen_ctx->io);
        }

        // Setup UDP
        if (mode != TCP_ONLY) {
            init_udprelay(server_host[index], server_port, m, auth, atoi(timeout),
                          iface);
        }

        LOGI("listening at %s:%s", host ? host : "*", server_port);

    }

    if (manager_address != NULL) {
        ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);
        ev_timer_start(EV_DEFAULT, &stat_update_watcher);
    }

    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
    }

    if (mode == UDP_ONLY) {
        LOGI("TCP relay disabled");
    }

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // start ev loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    if (manager_address != NULL) {
        ev_timer_stop(EV_DEFAULT, &stat_update_watcher);
    }

    // Clean up
    for (int i = 0; i <= server_num; i++) {
        struct listen_ctx *listen_ctx = &listen_ctx_list[i];
        if (mode != UDP_ONLY) {
            ev_io_stop(loop, &listen_ctx->io);
            close(listen_ctx->fd);
        }
    }

    if (mode != UDP_ONLY) {
        free_connections(loop);
    }

    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    resolv_shutdown(loop);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}
Exemplo n.º 7
0
int main(int argc, char *argv[])
{
	int c;
	const char *config_file = DEFAULT_CONFIG;
	const char *adm_socket = DEFAULT_ADM_SOCKET;
	int verbose = 0;
	static struct ev_loop *loop;
	static struct ev_signal signal_watcher;
	pid_t pid;

	while ((c = getopt(argc, argv, "a:c:dhp:Vv")) != -1) {
		switch (c) {
		case 'a':
			adm_socket = optarg;
			break;
		case 'c':
			config_file = optarg;
			break;
		case 'd':
			pingu_daemonize++;
			break;
		case 'h':
			return usage(basename(argv[0]));
		case 'p':
			pid_file = optarg;
			break;
		case 'V':
			print_version(basename(argv[0]));
			return 0;
		case 'v':
			verbose++;
			break;
		}
	}

	argc -= optind;
	argv += optind;

	log_init("pingu", verbose);

	pid = get_running_pid();
	if (pid)
		errx(1, "appears to be running already (pid %i)", pid);

	loop = ev_default_loop(0);

	if (pingu_conf_parse(config_file) < 0)
		return 1;

	if (pingu_iface_init(loop) < 0)
		return 1;

	if (pingu_host_init(loop) < 0)
		return 1;

	if (pingu_adm_init(loop, adm_socket) < 0)
		return 1;

	if (pingu_daemonize) {
		if (daemonize() == -1)
			return 1;
	}

	kernel_init(loop);
	ev_signal_init(&signal_watcher, sigint_cb, SIGINT);
	ev_signal_start(loop, &signal_watcher);

	ev_run(loop, 0);
	log_info("Shutting down");
	pingu_iface_cleanup(loop);
	pingu_host_cleanup();
	kernel_close();
	ev_loop_destroy(loop);
	return 0;
}
Exemplo n.º 8
0
Signal::Signal(STATE, ObjectCallback *chan, int sig):
    Event(state, chan), signal(sig) {
    ev_signal_init(&ev, event::tramp<struct ev_signal>, sig);
    ev.data = this;
}
Exemplo n.º 9
0
int main(int argc, char **argv) {
    int opt;
    int option_index = 0;
    char *socket_path = getenv("I3SOCK");
    char *command = NULL;
    char *fontname = NULL;
    char *i3_default_sock_path = "/tmp/i3-ipc.sock";
    struct xcb_color_strings_t colors = { NULL, };

    /* Definition of the standard-config */
    config.hide_on_modifier = 0;
    config.dockpos = DOCKPOS_NONE;
    config.disable_ws = 0;

    static struct option long_opt[] = {
        { "socket",               required_argument, 0, 's' },
        { "command",              required_argument, 0, 'c' },
        { "hide",                 no_argument,       0, 'm' },
        { "dock",                 optional_argument, 0, 'd' },
        { "font",                 required_argument, 0, 'f' },
        { "nows",                 no_argument,       0, 'w' },
        { "help",                 no_argument,       0, 'h' },
        { "version",              no_argument,       0, 'v' },
        { "verbose",              no_argument,       0, 'V' },
        { "color-bar-fg",         required_argument, 0, 'A' },
        { "color-bar-bg",         required_argument, 0, 'B' },
        { "color-active-ws-fg",   required_argument, 0, 'C' },
        { "color-active-ws-bg",   required_argument, 0, 'D' },
        { "color-inactive-ws-fg", required_argument, 0, 'E' },
        { "color-inactive-ws-bg", required_argument, 0, 'F' },
        { "color-urgent-ws-bg",   required_argument, 0, 'G' },
        { "color-urgent-ws-fg",   required_argument, 0, 'H' },
        { "color-focus-ws-bg",    required_argument, 0, 'I' },
        { "color-focus-ws-fg",    required_argument, 0, 'J' },
        { NULL,                   0,                 0, 0}
    };

    while ((opt = getopt_long(argc, argv, "s:c:d::mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) {
        switch (opt) {
            case 's':
                socket_path = expand_path(optarg);
                break;
            case 'c':
                command = strdup(optarg);
                break;
            case 'm':
                config.hide_on_modifier = 1;
                break;
            case 'd':
                config.hide_on_modifier = 0;
                if (optarg == NULL) {
                    config.dockpos = DOCKPOS_BOT;
                    break;
                }
                if (!strcmp(optarg, "top")) {
                    config.dockpos = DOCKPOS_TOP;
                } else if (!strcmp(optarg, "bottom")) {
                    config.dockpos = DOCKPOS_BOT;
                } else {
                    print_usage(argv[0]);
                    exit(EXIT_FAILURE);
                }
                break;
            case 'f':
                fontname = strdup(optarg);
                break;
            case 'w':
                config.disable_ws = 1;
                break;
            case 'v':
                printf("i3bar version " I3_VERSION " © 2010-2011 Axel Wagner and contributors\n");
                exit(EXIT_SUCCESS);
                break;
            case 'V':
                config.verbose = 1;
                break;
            case 'A':
                read_color(&colors.bar_fg);
                break;
            case 'B':
                read_color(&colors.bar_bg);
                break;
            case 'C':
                read_color(&colors.active_ws_fg);
                break;
            case 'D':
                read_color(&colors.active_ws_bg);
                break;
            case 'E':
                read_color(&colors.inactive_ws_fg);
                break;
            case 'F':
                read_color(&colors.inactive_ws_bg);
                break;
            case 'G':
                read_color(&colors.urgent_ws_bg);
                break;
            case 'H':
                read_color(&colors.urgent_ws_fg);
                break;
            case 'I':
                read_color(&colors.focus_ws_bg);
                break;
            case 'J':
                read_color(&colors.focus_ws_fg);
                break;
            default:
                print_usage(argv[0]);
                exit(EXIT_SUCCESS);
                break;
        }
    }

    if (fontname == NULL) {
        /* This is a very restrictive default. More sensefull would be something like
         * "-misc-*-*-*-*--*-*-*-*-*-*-*-*". But since that produces very ugly results
         * on my machine, let's stick with this until we have a configfile */
        fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1";
    }

    if (config.dockpos != DOCKPOS_NONE) {
        if (config.hide_on_modifier) {
            ELOG("--dock and --hide are mutually exclusive!\n");
            exit(EXIT_FAILURE);
        }
    } else {
        config.hide_on_modifier = 1;
    }

    main_loop = ev_default_loop(0);

    init_colors(&colors);
    char *atom_sock_path = init_xcb(fontname);

    if (socket_path == NULL) {
        socket_path = atom_sock_path;
    }

    if (socket_path == NULL) {
        ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path);
        socket_path = expand_path(i3_default_sock_path);
    }

    free_colors(&colors);

    init_outputs();
    if (init_connection(socket_path)) {
        /* We subscribe to the i3-events we need */
        subscribe_events();

        /* We initiate the main-function by requesting infos about the outputs and
         * workspaces. Everything else (creating the bars, showing the right workspace-
         * buttons and more) is taken care of by the event-driveniness of the code */
        i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
        if (!config.disable_ws) {
            i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
        }
    }

    /* The name of this function is actually misleading. Even if no -c is specified,
     * this function initiates the watchers to listen on stdin and react accordingly */
    start_child(command);
    FREE(command);

    /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop.
     * We only need those watchers on the stack, so putting them on the stack saves us
     * some calls to free() */
    ev_signal *sig_term = malloc(sizeof(ev_signal));
    ev_signal *sig_int = malloc(sizeof(ev_signal));
    ev_signal *sig_hup = malloc(sizeof(ev_signal));

    if (sig_term == NULL || sig_int == NULL || sig_hup == NULL) {
        ELOG("malloc() failed: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    ev_signal_init(sig_term, &sig_cb, SIGTERM);
    ev_signal_init(sig_int, &sig_cb, SIGINT);
    ev_signal_init(sig_hup, &sig_cb, SIGHUP);

    ev_signal_start(main_loop, sig_term);
    ev_signal_start(main_loop, sig_int);
    ev_signal_start(main_loop, sig_hup);

    /* From here on everything should run smooth for itself, just start listening for
     * events. We stop simply stop the event-loop, when we are finished */
    ev_loop(main_loop, 0);

    kill_child();

    FREE(statusline_buffer);

    clean_xcb();
    ev_default_destroy();

    free_workspaces();

    return 0;
}
Exemplo n.º 10
0
Arquivo: core.c Projeto: ifzz/lem
static inline void
signal_watcher_init(struct sigwatcher *s, int sig)
{
	ev_signal_init(&s->w, signal_os_handler, sig);
}
Exemplo n.º 11
0
int start_ss_local_server(profile_t profile)
{
    srand(time(NULL));

    char *remote_host = profile.remote_host;
    char *local_addr = profile.local_addr;
    char *method = profile.method;
    char *password = profile.password;
    char *log = profile.log;
    int remote_port = profile.remote_port;
    int local_port = profile.local_port;
    int timeout = profile.timeout;

    udprelay = profile.udp_relay;
    fast_open = profile.fast_open;
    verbose = profile.verbose;

    char local_port_str[16];
    char remote_port_str[16];
    sprintf(local_port_str, "%d", local_port);
    sprintf(remote_port_str, "%d", remote_port);

    USE_LOGFILE(log);

    if (profile.acl != NULL) {
        acl = !init_acl(profile.acl);
    }

    if (local_addr == NULL) {
        local_addr = "127.0.0.1";
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // Setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // Setup socket
    int listenfd;
    listenfd = create_and_bind(local_addr, local_port_str);
    if (listenfd < 0) {
        ERROR("bind()");
        return -1;
    }
    if (listen(listenfd, SOMAXCONN) == -1) {
        ERROR("listen()");
        return -1;
    }
    setnonblocking(listenfd);
    LOGI("listening at %s:%s", local_addr, local_port_str);

    // Setup proxy context
    struct listen_ctx listen_ctx;

    listen_ctx.remote_num = 1;
    listen_ctx.remote_addr = malloc(sizeof(struct sockaddr *));
    struct sockaddr_storage *storage = malloc(sizeof(struct sockaddr_storage));
    memset(storage, 0, sizeof(struct sockaddr_storage));
    if (get_sockaddr(remote_host, remote_port_str, storage) == -1) {
        return -1;
    }
    listen_ctx.remote_addr[0] = (struct sockaddr *)storage;
    listen_ctx.timeout = timeout;
    listen_ctx.fd = listenfd;
    listen_ctx.method = m;
    listen_ctx.iface = NULL;

    struct ev_loop *loop = EV_DEFAULT;
    ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ);
    ev_io_start(loop, &listen_ctx.io);

    // Setup UDP
    if (udprelay) {
        LOGI("udprelay enabled");
        init_udprelay(local_addr, local_port_str, listen_ctx.remote_addr[0],
                      get_sockaddr_len(listen_ctx.remote_addr[0]), m,
                      listen_ctx.timeout, NULL);
    }

    // Init connections
    cork_dllist_init(&connections);

    // Enter the loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    // Clean up
    free_connections(loop);
    if (udprelay) {
        free_udprelay();
    }

    ev_io_stop(loop, &listen_ctx.io);
    free(listen_ctx.remote_addr);
    close(listen_ctx.fd);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    // cannot reach here
    return 0;
}
Exemplo n.º 12
0
Arquivo: main.c Projeto: stfnm/i3
int main(int argc, char **argv) {
    int opt;
    int option_index = 0;
    char *socket_path = getenv("I3SOCK");
    char *i3_default_sock_path = "/tmp/i3-ipc.sock";

    /* Initialize the standard config to use 0 as default */
    memset(&config, '\0', sizeof(config_t));

    static struct option long_opt[] = {
        { "socket",               required_argument, 0, 's' },
        { "bar_id",               required_argument, 0, 0 },
        { "help",                 no_argument,       0, 'h' },
        { "version",              no_argument,       0, 'v' },
        { NULL,                   0,                 0, 0}
    };

    while ((opt = getopt_long(argc, argv, "s:hv", long_opt, &option_index)) != -1) {
        switch (opt) {
        case 's':
            socket_path = expand_path(optarg);
            break;
        case 'v':
            printf("i3bar version " I3_VERSION " © 2010-2011 Axel Wagner and contributors\n");
            exit(EXIT_SUCCESS);
            break;
        case 0:
            if (!strcmp(long_opt[option_index].name, "bar_id")) {
                FREE(config.bar_id);
                config.bar_id = sstrdup(optarg);
            }
            break;
        default:
            print_usage(argv[0]);
            exit(EXIT_SUCCESS);
            break;
        }
    }

    if (!config.bar_id) {
        /* TODO: maybe we want -f which will automatically ask i3 for the first
         * configured bar (and error out if there are too many)? */
        ELOG("No bar_id passed. Please let i3 start i3bar or specify --bar_id\n");
        exit(EXIT_FAILURE);
    }

    main_loop = ev_default_loop(0);

    char *atom_sock_path = init_xcb_early();

    if (socket_path == NULL) {
        socket_path = atom_sock_path;
    }

    if (socket_path == NULL) {
        ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path);
        socket_path = expand_path(i3_default_sock_path);
    }

    init_outputs();
    if (init_connection(socket_path)) {
        /* Request the bar configuration. When it arrives, we fill the config array. */
        i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG, config.bar_id);
    }

    /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop.
     * We only need those watchers on the stack, so putting them on the stack saves us
     * some calls to free() */
    ev_signal *sig_term = smalloc(sizeof(ev_signal));
    ev_signal *sig_int = smalloc(sizeof(ev_signal));
    ev_signal *sig_hup = smalloc(sizeof(ev_signal));

    ev_signal_init(sig_term, &sig_cb, SIGTERM);
    ev_signal_init(sig_int, &sig_cb, SIGINT);
    ev_signal_init(sig_hup, &sig_cb, SIGHUP);

    ev_signal_start(main_loop, sig_term);
    ev_signal_start(main_loop, sig_int);
    ev_signal_start(main_loop, sig_hup);

    /* From here on everything should run smooth for itself, just start listening for
     * events. We stop simply stop the event-loop, when we are finished */
    ev_loop(main_loop, 0);

    kill_child();

    FREE(statusline_buffer);

    clean_xcb();
    ev_default_destroy();

    free_workspaces();

    return 0;
}
Exemplo n.º 13
0
int main(int argc, char *argv[])
{
	const struct rlimit rlim = {
		.rlim_cur = RLIM_INFINITY,
		.rlim_max = RLIM_INFINITY
	};

	ev_signal signal_usr1;
	ev_signal signal_usr2;
	ev_signal signal_pipe;

	int c;

	/* unlimited size for cores */
	setrlimit(RLIMIT_CORE, &rlim);

	logx_level = LOG_INFO;

	while (1) {
		int option_index = 0;
		static struct option long_options[] = {
			{"log",       1, 0, 'l'},
			{0, 0, 0, 0}
		};

		c = getopt_long(argc, argv, "hl:x",
				long_options, &option_index);
		if (c == -1)
			break;

		switch (c) {
		case 'h':
			usage();
			break;

		case 'l': {
			struct in_addr addr;

			if (inet_aton(optarg, &addr) == 0) {
				fprintf(stderr, "Invalid IP address: '%s'\n", optarg);
				exit(EXIT_FAILURE);
			} else
				logx_remote(addr);
			break;
		}

		case 'x':
			logx_level = LOG_DEBUG;
			break;

		default:
			printf("?? getopt returned character code 0%o ??\n", c);
		}
	}

	logx_open(basename(argv[0]), 0, LOG_DAEMON);

	ev_signal_init(&signal_usr1, sig_usr1, SIGUSR1);
        ev_signal_start(EV_DEFAULT_ &signal_usr1);

        ev_signal_init(&signal_usr2, sig_usr2, SIGUSR2);
        ev_signal_start(EV_DEFAULT_ &signal_usr2);

        ev_signal_init(&signal_pipe, sig_pipe, SIGPIPE);
        ev_signal_start(EV_DEFAULT_ &signal_pipe);

	init_comm(EV_DEFAULT);

	logx(LOG_NOTICE, "startup %s %s (pid %d)\n", _ident, _build, getpid());

	ev_run(EV_DEFAULT, 0);

        return 0;
}
Exemplo n.º 14
0
int main(int argc, char *argv[])
{
	struct sigaction sa;
	struct rlimit limit;
	int i, c, rc;
	int opt_foreground = 0, opt_allow_links = 0;
	enum startup_state opt_startup = startup_enable;
	extern char *optarg;
	extern int optind;
	struct ev_loop *loop;
	struct ev_io netlink_watcher;
	struct ev_signal sigterm_watcher;
	struct ev_signal sighup_watcher;
	struct ev_signal sigusr1_watcher;
	struct ev_signal sigusr2_watcher;
	struct ev_signal sigchld_watcher;

	/* Get params && set mode */
	while ((c = getopt(argc, argv, "flns:")) != -1) {
		switch (c) {
		case 'f':
			opt_foreground = 1;
			break;
		case 'l':
			opt_allow_links=1;
			break;
		case 'n':
			do_fork = 0;
			break;
		case 's':
			for (i=0; i<startup_INVALID; i++) {
				if (strncmp(optarg, startup_states[i],
					strlen(optarg)) == 0) {
					opt_startup = i;
					break;
				}
			}
			if (i == startup_INVALID) {
				fprintf(stderr, "unknown startup mode '%s'\n",
					optarg);
				usage();
			}
			break;
		default:
			usage();
		}
	}

	/* check for trailing command line following options */
	if (optind < argc) {
		usage();
	}

	if (opt_allow_links)
		set_allow_links(1);

	if (opt_foreground) {
		config.daemonize = D_FOREGROUND;
		set_aumessage_mode(MSG_STDERR, DBG_YES);
	} else {
		config.daemonize = D_BACKGROUND;
		set_aumessage_mode(MSG_SYSLOG, DBG_NO);
		(void) umask( umask( 077 ) | 022 );
	}

#ifndef DEBUG
	/* Make sure we are root */
	if (getuid() != 0) {
		fprintf(stderr, "You must be root to run this program.\n");
		return 4;
	}
#endif

	/* Register sighandlers */
	sa.sa_flags = 0 ;
	sigemptyset( &sa.sa_mask ) ;
	/* Ignore all signals by default */
	sa.sa_handler = SIG_IGN;
	for (i=1; i<NSIG; i++)
		sigaction( i, &sa, NULL );

	atexit(clean_exit);

	/* Raise the rlimits in case we're being started from a shell
         * with restrictions. Not a fatal error.  */
	limit.rlim_cur = RLIM_INFINITY;
	limit.rlim_max = RLIM_INFINITY;
	setrlimit(RLIMIT_FSIZE, &limit);
	setrlimit(RLIMIT_CPU, &limit);

	/* Load the Configuration File */
	if (load_config(&config, TEST_AUDITD))
		return 6;

	if (config.priority_boost != 0) {
		errno = 0;
		rc = nice((int)-config.priority_boost);
		if (rc == -1 && errno) {
			audit_msg(LOG_ERR, "Cannot change priority (%s)", 
					strerror(errno));
			return 1;
		}
	} 
	
	/* Daemonize or stay in foreground for debugging */
	if (config.daemonize == D_BACKGROUND) {
		if (become_daemon() != 0) {
			audit_msg(LOG_ERR, "Cannot daemonize (%s)",
				strerror(errno));
			tell_parent(FAILURE);
			return 1;
		} 
		openlog("auditd", LOG_PID, LOG_DAEMON);
	}

	/* Init netlink */
	if ((fd = audit_open()) < 0) {
        	audit_msg(LOG_ERR, "Cannot open netlink audit socket");
		tell_parent(FAILURE);
		return 1;
	}

	/* Init the event handler thread */
	write_pid_file();
	if (init_event(&config)) {
		if (pidfile)
			unlink(pidfile);
		tell_parent(FAILURE);
		return 1;
	}

	if (init_dispatcher(&config)) {
		if (pidfile)
			unlink(pidfile);
		tell_parent(FAILURE);
		return 1;
	}

	/* Get machine name ready for use */
	if (resolve_node(&config)) {
		if (pidfile)
			unlink(pidfile);
		tell_parent(FAILURE);
		return 1;
	}

	/* Write message to log that we are alive */
	{
		struct utsname ubuf;
		char start[DEFAULT_BUF_SZ];
		const char *fmt = audit_lookup_format((int)config.log_format);
		if (fmt == NULL)
			fmt = "UNKNOWN";
		if (uname(&ubuf) != 0) {
			if (pidfile)
				unlink(pidfile);
			tell_parent(FAILURE);
			return 1;
		}
		if (getsubj(subj))
			snprintf(start, sizeof(start),
				"auditd start, ver=%s format=%s "
			    "kernel=%.56s auid=%u pid=%d subj=%s res=success",
				VERSION, fmt, ubuf.release,
				audit_getloginuid(), getpid(), subj);
		else
			snprintf(start, sizeof(start),
				"auditd start, ver=%s format=%s "
				"kernel=%.56s auid=%u pid=%d res=success",
				VERSION, fmt, ubuf.release,
				audit_getloginuid(), getpid());
		if (send_audit_event(AUDIT_DAEMON_START, start)) {
        		audit_msg(LOG_ERR, "Cannot send start message");
			if (pidfile)
				unlink(pidfile);
			shutdown_dispatcher();
			tell_parent(FAILURE);
			return 1;
		}
	}

	/* Tell kernel not to kill us */
	avoid_oom_killer();

	/* let config manager init */
	init_config_manager();

	if (opt_startup != startup_nochange && (audit_is_enabled(fd) < 2) &&
	    audit_set_enabled(fd, (int)opt_startup) < 0) {
		char emsg[DEFAULT_BUF_SZ];
		if (*subj)
			snprintf(emsg, sizeof(emsg),
			"auditd error halt, auid=%u pid=%d subj=%s res=failed",
				audit_getloginuid(), getpid(), subj);
		else
			snprintf(emsg, sizeof(emsg),
				"auditd error halt, auid=%u pid=%d res=failed",
				audit_getloginuid(), getpid());
		stop = 1;
		send_audit_event(AUDIT_DAEMON_ABORT, emsg);
		audit_msg(LOG_ERR,
		"Unable to set initial audit startup state to '%s', exiting",
			startup_states[opt_startup]);
		close_down();
		if (pidfile)
			unlink(pidfile);
		shutdown_dispatcher();
		tell_parent(FAILURE);
		return 1;
	}

	/* Tell the kernel we are alive */
	if (audit_set_pid(fd, getpid(), WAIT_YES) < 0) {
		char emsg[DEFAULT_BUF_SZ];
		if (*subj)
			snprintf(emsg, sizeof(emsg),
			"auditd error halt, auid=%u pid=%d subj=%s res=failed",
				audit_getloginuid(), getpid(), subj);
		else
			snprintf(emsg, sizeof(emsg),
				"auditd error halt, auid=%u pid=%d res=failed",
				audit_getloginuid(), getpid());
		stop = 1;
		send_audit_event(AUDIT_DAEMON_ABORT, emsg);
		audit_msg(LOG_ERR, "Unable to set audit pid, exiting");
		close_down();
		if (pidfile)
			unlink(pidfile);
		shutdown_dispatcher();
		tell_parent(FAILURE);
		return 1;
	}

	/* Depending on value of opt_startup (-s) set initial audit state */
	loop = ev_default_loop (EVFLAG_NOENV);

	ev_io_init (&netlink_watcher, netlink_handler, fd, EV_READ);
	ev_io_start (loop, &netlink_watcher);

	ev_signal_init (&sigterm_watcher, term_handler, SIGTERM);
	ev_signal_start (loop, &sigterm_watcher);

	ev_signal_init (&sighup_watcher, hup_handler, SIGHUP);
	ev_signal_start (loop, &sighup_watcher);

	ev_signal_init (&sigusr1_watcher, user1_handler, SIGUSR1);
	ev_signal_start (loop, &sigusr1_watcher);

	ev_signal_init (&sigusr2_watcher, user2_handler, SIGUSR2);
	ev_signal_start (loop, &sigusr2_watcher);

	ev_signal_init (&sigchld_watcher, child_handler, SIGCHLD);
	ev_signal_start (loop, &sigchld_watcher);

	if (auditd_tcp_listen_init (loop, &config)) {
		char emsg[DEFAULT_BUF_SZ];
		if (*subj)
			snprintf(emsg, sizeof(emsg),
			"auditd error halt, auid=%u pid=%d subj=%s res=failed",
				audit_getloginuid(), getpid(), subj);
		else
			snprintf(emsg, sizeof(emsg),
				"auditd error halt, auid=%u pid=%d res=failed",
				audit_getloginuid(), getpid());
		stop = 1;
		send_audit_event(AUDIT_DAEMON_ABORT, emsg);
		tell_parent(FAILURE);
	} else {
		/* Now tell parent that everything went OK */
		tell_parent(SUCCESS);
		audit_msg(LOG_NOTICE,
	    "Init complete, auditd %s listening for events (startup state %s)",
			VERSION,
			startup_states[opt_startup]);
	}

	/* Parent should be gone by now...   */
	if (do_fork)
		close(init_pipe[1]);

	// Init complete, start event loop
	if (!stop)
		ev_loop (loop, 0);

	auditd_tcp_listen_uninit (loop, &config);

	// Tear down IO watchers Part 1
	ev_signal_stop (loop, &sighup_watcher);
	ev_signal_stop (loop, &sigusr1_watcher);
	ev_signal_stop (loop, &sigusr2_watcher);
	ev_signal_stop (loop, &sigterm_watcher);

	/* Write message to log that we are going down */
	rc = audit_request_signal_info(fd);
	if (rc > 0) {
		struct audit_reply trep;

		rc = get_reply(fd, &trep, rc);
		if (rc > 0) {
			char txt[MAX_AUDIT_MESSAGE_LENGTH];
			snprintf(txt, sizeof(txt),
				"auditd normal halt, sending auid=%u "
				"pid=%d subj=%s res=success",
				 trep.signal_info->uid,
				 trep.signal_info->pid, 
				 trep.signal_info->ctx); 
			send_audit_event(AUDIT_DAEMON_END, txt);
		} 
	} 
	if (rc <= 0)
		send_audit_event(AUDIT_DAEMON_END, 
				"auditd normal halt, sending auid=? "
				"pid=? subj=? res=success");
	free(rep);

	// Tear down IO watchers Part 2
	ev_io_stop (loop, &netlink_watcher);

	// Give DAEMON_END event a little time to be sent in case
	// of remote logging
	usleep(10000); // 10 milliseconds
	shutdown_dispatcher();

	// Tear down IO watchers Part 3
	ev_signal_stop (loop, &sigchld_watcher);

	close_down();
	free_config(&config);
	ev_default_destroy();

	return 0;
}
Exemplo n.º 15
0
/** Hello, this is main.
 * \param argc Who knows.
 * \param argv Who knows.
 * \return EXIT_SUCCESS I hope.
 */
int
main(int argc, char **argv)
{
    char *confpath = NULL;
    int xfd, i, opt;
    ssize_t cmdlen = 1;
    xdgHandle xdg;
    bool no_argb = false;
    xcb_generic_event_t *event;
    xcb_query_tree_cookie_t tree_c;
    static struct option long_options[] =
    {
        { "help",    0, NULL, 'h' },
        { "version", 0, NULL, 'v' },
        { "config",  1, NULL, 'c' },
        { "check",   0, NULL, 'k' },
        { "no-argb", 0, NULL, 'a' },
        { NULL,      0, NULL, 0 }
    };

    /* event loop watchers */
    ev_io xio    = { .fd = -1 };
    ev_check xcheck;
    ev_prepare a_refresh;
    ev_signal sigint;
    ev_signal sigterm;
    ev_signal sighup;

    /* clear the globalconf structure */
    p_clear(&globalconf, 1);
    globalconf.keygrabber = LUA_REFNIL;
    globalconf.mousegrabber = LUA_REFNIL;
    buffer_init(&globalconf.startup_errors);

    /* save argv */
    for(i = 0; i < argc; i++)
        cmdlen += a_strlen(argv[i]) + 1;

    awesome_argv = p_new(char, cmdlen);
    a_strcpy(awesome_argv, cmdlen, argv[0]);

    for(i = 1; i < argc; i++)
    {
        a_strcat(awesome_argv, cmdlen, " ");
        a_strcat(awesome_argv, cmdlen, argv[i]);
    }

    /* Text won't be printed correctly otherwise */
    setlocale(LC_CTYPE, "");

    /* Get XDG basedir data */
    xdgInitHandle(&xdg);

    /* init lua */
    luaA_init(&xdg);

    /* check args */
    while((opt = getopt_long(argc, argv, "vhkc:a",
                             long_options, NULL)) != -1)
        switch(opt)
        {
        case 'v':
            eprint_version();
            break;
        case 'h':
            exit_help(EXIT_SUCCESS);
            break;
        case 'k':
            if(!luaA_parserc(&xdg, confpath, false))
            {
                fprintf(stderr, "✘ Configuration file syntax error.\n");
                return EXIT_FAILURE;
            }
            else
            {
                fprintf(stderr, "✔ Configuration file syntax OK.\n");
                return EXIT_SUCCESS;
            }
        case 'c':
            if(a_strlen(optarg))
                confpath = a_strdup(optarg);
            else
                fatal("-c option requires a file name");
            break;
        case 'a':
            no_argb = true;
            break;
        }

    globalconf.loop = ev_default_loop(EVFLAG_NOSIGFD);

    /* register function for signals */
    ev_signal_init(&sigint, exit_on_signal, SIGINT);
    ev_signal_init(&sigterm, exit_on_signal, SIGTERM);
    ev_signal_init(&sighup, restart_on_signal, SIGHUP);
    ev_signal_start(globalconf.loop, &sigint);
    ev_signal_start(globalconf.loop, &sigterm);
    ev_signal_start(globalconf.loop, &sighup);
    ev_unref(globalconf.loop);
    ev_unref(globalconf.loop);
    ev_unref(globalconf.loop);

    struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 };
    sigemptyset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);

    /* X stuff */
    globalconf.connection = xcb_connect(NULL, &globalconf.default_screen);
    if(xcb_connection_has_error(globalconf.connection))
        fatal("cannot open display");

    globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen);
    /* FIXME The following two assignments were swapped on purpose */
    if(!no_argb)
        globalconf.visual = a_default_visual(globalconf.screen);
    if(!globalconf.visual)
        globalconf.visual = a_argb_visual(globalconf.screen);
    globalconf.default_depth = a_visual_depth(globalconf.screen, globalconf.visual->visual_id);
    globalconf.default_cmap = globalconf.screen->default_colormap;
    if(globalconf.default_depth != globalconf.screen->root_depth)
    {
        // We need our own color map if we aren't using the default depth
        globalconf.default_cmap = xcb_generate_id(globalconf.connection);
        xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE,
                            globalconf.default_cmap, globalconf.screen->root,
                            globalconf.visual->visual_id);
    }

    /* Prefetch all the extensions we might need */
    xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_xinerama_id);

    /* initialize dbus */
    a_dbus_init();

    /* Get the file descriptor corresponding to the X connection */
    xfd = xcb_get_file_descriptor(globalconf.connection);
    ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ);
    ev_io_start(globalconf.loop, &xio);
    ev_check_init(&xcheck, &a_xcb_check_cb);
    ev_check_start(globalconf.loop, &xcheck);
    ev_unref(globalconf.loop);
    ev_prepare_init(&a_refresh, &a_refresh_cb);
    ev_prepare_start(globalconf.loop, &a_refresh);
    ev_unref(globalconf.loop);

    /* Grab server */
    xcb_grab_server(globalconf.connection);

    /* Make sure there are no pending events. Since we didn't really do anything
     * at all yet, we will just discard all events which we received so far.
     * The above GrabServer should make sure no new events are generated. */
    xcb_aux_sync(globalconf.connection);
    while ((event = xcb_poll_for_event(globalconf.connection)) != NULL)
    {
        /* Make sure errors are printed */
        uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event);
        if(response_type == 0)
            event_handle(event);
        p_delete(&event);
    }

    {
        const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;

        /* This causes an error if some other window manager is running */
        xcb_change_window_attributes(globalconf.connection,
                                     globalconf.screen->root,
                                     XCB_CW_EVENT_MASK, &select_input_val);
    }

    /* Need to xcb_flush to validate error handler */
    xcb_aux_sync(globalconf.connection);

    /* Process all errors in the queue if any. There can be no events yet, so if
     * this function returns something, it must be an error. */
    if (xcb_poll_for_event(globalconf.connection) != NULL)
        fatal("another window manager is already running");

    /* Prefetch the maximum request length */
    xcb_prefetch_maximum_request_length(globalconf.connection);

    /* check for xtest extension */
    const xcb_query_extension_reply_t *xtest_query;
    xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id);
    globalconf.have_xtest = xtest_query->present;

    /* Allocate the key symbols */
    globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection);
    xcb_get_modifier_mapping_cookie_t xmapping_cookie =
        xcb_get_modifier_mapping_unchecked(globalconf.connection);

    /* init atom cache */
    atoms_init(globalconf.connection);

    /* init screens information */
    screen_scan();

    xutil_lock_mask_get(globalconf.connection, xmapping_cookie,
                        globalconf.keysyms, &globalconf.numlockmask,
                        &globalconf.shiftlockmask, &globalconf.capslockmask,
                        &globalconf.modeswitchmask);

    /* do this only for real screen */
    ewmh_init();
    systray_init();

    /* init spawn (sn) */
    spawn_init();

    /* The default GC is just a newly created associated with a window with
     * depth globalconf.default_depth */
    xcb_window_t tmp_win = xcb_generate_id(globalconf.connection);
    globalconf.gc = xcb_generate_id(globalconf.connection);
    xcb_create_window(globalconf.connection, globalconf.default_depth,
                      tmp_win, globalconf.screen->root,
                      -1, -1, 1, 1, 0,
                      XCB_COPY_FROM_PARENT, globalconf.visual->visual_id,
                      XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP,
                      (const uint32_t [])
    {
        globalconf.screen->black_pixel,
                          globalconf.screen->black_pixel,
                          globalconf.default_cmap
    });
    xcb_create_gc(globalconf.connection, globalconf.gc, tmp_win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,
    (const uint32_t[]) {
        globalconf.screen->black_pixel, globalconf.screen->white_pixel
    });
    xcb_destroy_window(globalconf.connection, tmp_win);

    /* Get the window tree associated to this screen */
    tree_c = xcb_query_tree_unchecked(globalconf.connection,
                                      globalconf.screen->root);

    xcb_change_window_attributes(globalconf.connection,
                                 globalconf.screen->root,
                                 XCB_CW_EVENT_MASK,
                                 ROOT_WINDOW_EVENT_MASK);

    /* we will receive events, stop grabbing server */
    xcb_ungrab_server(globalconf.connection);

    /* Parse and run configuration file */
    if (!luaA_parserc(&xdg, confpath, true))
        fatal("couldn't find any rc file");

    p_delete(&confpath);

    xdgWipeHandle(&xdg);

    /* scan existing windows */
    scan(tree_c);

    xcb_flush(globalconf.connection);

    /* main event loop */
    ev_loop(globalconf.loop, 0);

    /* cleanup event loop */
    ev_ref(globalconf.loop);
    ev_check_stop(globalconf.loop, &xcheck);
    ev_ref(globalconf.loop);
    ev_prepare_stop(globalconf.loop, &a_refresh);
    ev_ref(globalconf.loop);
    ev_io_stop(globalconf.loop, &xio);

    awesome_atexit(false);

    return EXIT_SUCCESS;
}
Exemplo n.º 16
0
int main(int argc, char **argv)
{
    int do_fork = 1;
    char *config_fn = DEFAULT_CONFIG_FILE;
    char *pid_fn = DEFAULT_PID_FILE;
    int c;

    evloop = EV_DEFAULT;
    ev_started_at = ev_time();

    opterr = 0;

    while ((c = getopt (argc, argv, "vhdfc:p:s:l:")) != -1) {
	switch (c) {
	case 'v':
	    verbose++;
	    break;
	case 'h':
	    usage(0);
	    return 0;
	case 'd':
	    debug = 1;
	    do_fork = 0;
	    break;
	case 'f':
	    do_fork = 0;
	    break;
	case 'c':
	    config_fn = optarg;
	    break;
	case 'p':
	    pid_fn = optarg;
	    break;
	case 's':
	    server_str_id = strdup(optarg);
	    break;
	case 'l':
	    server_listen_port = atoi(optarg);
	    if (server_listen_port < 1 || server_listen_port > 65534){
		fprintf (stderr, "Invalid listen port: %s.\n", optarg);
		return 1;
	    }
	    break;
	case '?':
	    if ((optopt == 'c') || (optopt == 'p') || (optopt == 's') || (optopt == 'l'))
		fprintf (stderr, "Option -%c requires an argument.\n", optopt);
	    else if (isprint (optopt))
		fprintf (stderr, "Unknown option `-%c'.\n", optopt);
	    else
		fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);

	    return 1;

	default:
	    usage();
	    return 1;
	}
    }

    if (optind < argc) {
	fprintf (stderr, "Unknown option: %s.\n", argv[optind]);
	return 1;
    }


    rtsp_server = rtsp_alloc();
    if (!rtsp_server){
	return 0;
    }

    log_to_stderr = !do_fork;

    if (!log_to_stderr)
	openlog(PROGRAM_NAME, LOG_PID, LOG_DAEMON);

    if (load_config(config_fn)) {
	fprintf (stderr, "Error loading config file.\n");
	return 2;
    }

    my_random_init();

    if (do_fork){
	log_debug("forking...");
	if (daemon(0, 0)){
	    log_error("daemonize failed: %s", strerror(errno));
	    return -1;
	}
	if (write_pid_file(pid_fn)){
	    log_warning("failed to create pid file");
	}
	ev_loop_fork(evloop);
    }


    if (!do_fork) {
	ev_signal_init (&signal_watcher1, sig_term_cb, SIGINT);
	ev_signal_start (evloop, &signal_watcher1);
    }

    ev_signal_init (&signal_watcher2, sig_term_cb, SIGTERM);
    ev_signal_start (evloop, &signal_watcher2);

    ev_signal_init (&signal_watcher3, sig_ignore_cb, SIGHUP);
    ev_signal_start (evloop, &signal_watcher3);

    ev_signal_init (&signal_watcher4, sig_ignore_cb, SIGPIPE);
    ev_signal_start (evloop, &signal_watcher4);


    if (csconv_init()){
	return 0;
    }
    if (rtsp_init(rtsp_server)){
	csconv_cleanup();
	return 0;
    }

    elevate_privileges();

    setup_io_prio();

    drop_privileges();

    log_info("starting...");

    ev_run(evloop, 0);

    log_info("cleaning up...");

    rtsp_cleanup(rtsp_server);

    csconv_cleanup();

    if (server_str_id)
	free(server_str_id);

    log_info("exiting...");

    if (!log_to_stderr)
	closelog();

    return 0;
}