Example #1
0
CAMLprim value ocaml_sd_listen_fds(value connect_to)
{
	CAMLparam1(connect_to);
	CAMLlocal1(sock_ret);
	int sock = -EBADR, n;

	n = sd_listen_fds(0);
	if (n <= 0) {
		sd_notifyf(0, "STATUS=Failed to get any active sockets: %s\n"
			   "ERRNO=%i",
			   strerror(errno),
			   errno);
		caml_failwith("ocaml_sd_listen_fds() failed to get any sockets");
	} else if (n != 2) {
		fprintf(stderr, SD_ERR "Expected 2 fds but given %d\n", n);
		sd_notifyf(0, "STATUS=Mismatch on number (2): %s\n"
			   "ERRNO=%d",
			   strerror(EBADR),
			   EBADR);
		caml_failwith("ocaml_sd_listen_fds() mismatch");
	}

	sock = oxen_verify_socket_socket(String_val(connect_to));
	if (sock <= 0) {
		fprintf(stderr, "failed to verify sock %s\n",
			String_val(connect_to));
		caml_failwith("ocaml_sd_listen_fds_init() invalid socket");
	}

	sock_ret = Val_int(sock);

	CAMLreturn(sock_ret);
}
Example #2
0
int main(void)
{
	sd_listen_fds(true);
	sd_notify_supported();
	sd_notify(false, "XXX");
	sd_notifyf(false, "foo=%s", "bar");
}
Example #3
0
static void raw_pull_report_progress(RawPull *i, RawProgress p) {
        unsigned percent;

        assert(i);

        switch (p) {

        case RAW_DOWNLOADING: {
                unsigned remain = 80;

                percent = 0;

                if (i->settings_job) {
                        percent += i->settings_job->progress_percent * 5 / 100;
                        remain -= 5;
                }

                if (i->roothash_job) {
                        percent += i->roothash_job->progress_percent * 5 / 100;
                        remain -= 5;
                }

                if (i->checksum_job) {
                        percent += i->checksum_job->progress_percent * 5 / 100;
                        remain -= 5;
                }

                if (i->signature_job) {
                        percent += i->signature_job->progress_percent * 5 / 100;
                        remain -= 5;
                }

                if (i->raw_job)
                        percent += i->raw_job->progress_percent * remain / 100;
                break;
        }

        case RAW_VERIFYING:
                percent = 80;
                break;

        case RAW_UNPACKING:
                percent = 85;
                break;

        case RAW_FINALIZING:
                percent = 90;
                break;

        case RAW_COPYING:
                percent = 95;
                break;

        default:
                assert_not_reached("Unknown progress state");
        }

        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
        log_debug("Combined progress %u%%", percent);
}
Example #4
0
_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group, bool log_stdout)
{
	pid_t newpid;
	if (do_fork) {
		newpid = fork();
		if (newpid) {
#if HAVE_SYSTEMD
			sd_notifyf(0, "READY=0\nSTATUS=Starting process...\nMAINPID=%lu", (unsigned long) newpid);
#endif /* HAVE_SYSTEMD */
			_exit(0);
		}
	}

	/* detach from the terminal */
#ifdef HAVE_SETSID
	if (!no_process_group) setsid();
#elif defined(TIOCNOTTY)
	if (!no_process_group) {
		int i = open("/dev/tty", O_RDWR, 0);
		if (i != -1) {
			ioctl(i, (int) TIOCNOTTY, (char *)0);
			close(i);
		}
	}
#endif /* HAVE_SETSID */

	/* Close fd's 0,1,2 as appropriate. Needed if started by rsh. */
	/* stdin must be open if we do not fork, for monitoring for
	 * close.  stdout must be open if we are logging there, and we
	 * never close stderr (but debug might dup it onto a log file) */
	close_low_fds(do_fork, !log_stdout, false);
}
Example #5
0
			void ServiceNotification::serviceDisabled(std::string message){
#if defined(TBS_DEVICE)
				LOG_STREAM_DEBUG << "ServiceNotification::serviceDisabled: " << message << LE;
				std::string msg = "READY=0\n"
								"STATUS=" + message + "\n"
								"MAINPID=%lu";
				sd_notifyf(0,msg.c_str(), (unsigned long) getpid());
#endif
			}
Example #6
0
_PUBLIC_ void daemon_status(const char *name, const char *msg)
{
	if (name == NULL) {
		name = "Samba";
	}
#ifdef HAVE_SYSTEMD
	sd_notifyf(0, "\nSTATUS=%s: %s", name, msg);
#endif
	DEBUG(0, ("STATUS=daemon '%s' : %s", name, msg));
}
Example #7
0
_PUBLIC_ void daemon_ready(const char *daemon)
{
	if (daemon == NULL) {
		daemon = "Samba";
	}
#ifdef HAVE_SYSTEMD
	sd_notifyf(0, "READY=1\nSTATUS=%s: ready to serve connections...", daemon);
#endif
	DEBUG(0, ("STATUS=daemon '%s' finished starting up and ready to serve connections", daemon));
}
Example #8
0
static void
reportStatus (void)
{
    const double up = tr_sessionGetRawSpeed_KBps (mySession, TR_UP);
    const double dn = tr_sessionGetRawSpeed_KBps (mySession, TR_DOWN);

    if (up>0 || dn>0)
	sd_notifyf (0, "STATUS=Uploading %.2f KBps, Downloading %.2f KBps.\n", up, dn);
    else
	sd_notify (0, "STATUS=Idle.\n");
}
Example #9
0
static int oxen_verify_socket_socket(const char *connect_to)
{
	if ((strcmp(XEN_RUN_STORED "/socket_ro", connect_to) != 0) &&
	    (strcmp(XEN_RUN_STORED "/socket", connect_to) != 0)) {
		sd_notifyf(0, "STATUS=unexpected socket: %s\n"
			   "ERRNO=%i",
			   connect_to,
			   EBADR);
		return -EBADR;
	}

	return oxen_get_sd_fd(connect_to);
}
Example #10
0
_PUBLIC_ void exit_daemon(const char *msg, int error)
{
#ifdef HAVE_SYSTEMD
	if (msg == NULL) {
		msg = strerror(error);
	}

	sd_notifyf(0, "STATUS=daemon failed to start: %s\n"
				  "ERRNO=%i",
				  msg,
				  error);
#endif
	DEBUG(0, ("STATUS=daemon failed to start: %s, error code %d\n", msg, error));
	exit(1);
}
Example #11
0
/* assume first argument after "fmt" is for DAEMON_NAME, that is
   really not of interest in our "nametag" function based on
   sd_notify (that very data point is provided implicitly) */
void sd_notify_wrapper(const char *fmt, ...)
{
	/* assume that first %s in fmt is intended for DAEMON_NAME,
	   i.e., for first argument following fmt in original
	   set_proc_title invocation, which has already been dropped
	   before it boils down here (using the wrapping macro trick);
	   we now simply append the reset after that first %s
	   (with whitespace stripped) to the "Running: " prefix */
	int rv;
	char buffer[255];
	char *fmt_iter;
	char *suffix = NULL;
	va_list ap;

	switch (local->type) {
		case ARBITRATOR:
		case GEOSTORE:
			break;
		default:
			return;  /* not expected to be run as system service */
	}

	fmt_iter = strchr(fmt, '%');
	while (fmt_iter) {
		switch (*++fmt_iter) {
			case 's': suffix = fmt_iter;
				  /* fall through */
			default: fmt_iter = NULL;
		}
	}
	if (!suffix) {
		log_warn("%s:%d: invalid format: %s", __FILE__, __LINE__, fmt);
		return;
	}
	while (isspace(*++suffix)) /* noop */ ;

	va_start(ap, fmt);
	fmt_iter = va_arg(ap, char *);  /* just shift by one */
	assert(!strcmp(fmt_iter, DAEMON_NAME));
	rv = vsnprintf(buffer, sizeof(buffer), suffix, ap);
	va_end(ap);

	rv = sd_notifyf(0, "READY=1\n"
			"STATUS=Running: %s",
			buffer);
	if (rv < 0)
		log_warn("%s:%d: sd_notifyf fail", __FILE__, __LINE__);
}
Example #12
0
static void dkr_pull_report_progress(DkrPull *i, DkrProgress p) {
        unsigned percent;

        assert(i);

        switch (p) {

        case DKR_SEARCHING:
                percent = 0;
                if (i->images_job)
                        percent += i->images_job->progress_percent * 5 / 100;
                break;

        case DKR_RESOLVING:
                percent = 5;
                if (i->tags_job)
                        percent += i->tags_job->progress_percent * 5 / 100;
                break;

        case DKR_METADATA:
                percent = 10;
                if (i->ancestry_job)
                        percent += i->ancestry_job->progress_percent * 5 / 100;
                if (i->json_job)
                        percent += i->json_job->progress_percent * 5 / 100;
                break;

        case DKR_DOWNLOADING:
                percent = 20;
                percent += 75 * i->current_ancestry / MAX(1U, i->n_ancestry);
                if (i->layer_job)
                        percent += i->layer_job->progress_percent * 75 / MAX(1U, i->n_ancestry) / 100;

                break;

        case DKR_COPYING:
                percent = 95;
                break;

        default:
                assert_not_reached("Unknown progress state");
        }

        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
        log_debug("Combined progress %u%%", percent);
}
Example #13
0
static void tar_pull_report_progress(TarPull *i, TarProgress p) {
        unsigned percent;

        assert(i);

        switch (p) {

        case TAR_DOWNLOADING: {
                unsigned remain = 85;

                percent = 0;

                if (i->checksum_job) {
                        percent += i->checksum_job->progress_percent * 5 / 100;
                        remain -= 5;
                }

                if (i->signature_job) {
                        percent += i->signature_job->progress_percent * 5 / 100;
                        remain -= 5;
                }

                if (i->tar_job)
                        percent += i->tar_job->progress_percent * remain / 100;
                break;
        }

        case TAR_VERIFYING:
                percent = 85;
                break;

        case TAR_FINALIZING:
                percent = 90;
                break;

        case TAR_COPYING:
                percent = 95;
                break;

        default:
                assert_not_reached("Unknown progress state");
        }

        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
        log_debug("Combined progress %u%%", percent);
}
Example #14
0
static void raw_export_report_progress(RawExport *e) {
        unsigned percent;
        assert(e);

        if (e->written_uncompressed >= (uint64_t) e->st.st_size)
                percent = 100;
        else
                percent = (unsigned) ((e->written_uncompressed * UINT64_C(100)) / (uint64_t) e->st.st_size);

        if (percent == e->last_percent)
                return;

        if (!ratelimit_below(&e->progress_rate_limit))
                return;

        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
        log_info("Exported %u%%.", percent);

        e->last_percent = percent;
}
Example #15
0
static void tar_export_report_progress(TarExport *e) {
    unsigned percent;
    assert(e);

    /* Do we have any quota info? If not, we don't know anything about the progress */
    if (e->quota_referenced == (uint64_t) -1)
        return;

    if (e->written_uncompressed >= e->quota_referenced)
        percent = 100;
    else
        percent = (unsigned) ((e->written_uncompressed * UINT64_C(100)) / e->quota_referenced);

    if (percent == e->last_percent)
        return;

    if (!ratelimit_test(&e->progress_rate_limit))
        return;

    sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
    log_info("Exported %u%%.", percent);

    e->last_percent = percent;
}
Example #16
0
static void raw_import_report_progress(RawImport *i) {
        unsigned percent;
        assert(i);

        /* We have no size information, unless the source is a regular file */
        if (!S_ISREG(i->st.st_mode))
                return;

        if (i->written_compressed >= (uint64_t) i->st.st_size)
                percent = 100;
        else
                percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size);

        if (percent == i->last_percent)
                return;

        if (!ratelimit_below(&i->progress_rate_limit))
                return;

        sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
        log_info("Imported %u%%.", percent);

        i->last_percent = percent;
}
Example #17
0
static void server_callback(AvahiServer *s, AvahiServerState state, void *userdata) {
    DaemonConfig *c = userdata;

    assert(s);
    assert(c);

    /* This function is possibly called before the global variable
     * avahi_server has been set, therefore we do it explicitly */

    avahi_server = s;

#ifdef HAVE_DBUS
    if (c->enable_dbus && state != AVAHI_SERVER_INVALID && state != AVAHI_SERVER_FAILURE)
        dbus_protocol_server_state_changed(state);
#endif

    switch (state) {
        case AVAHI_SERVER_RUNNING:
            avahi_log_info("Server startup complete. Host name is %s. Local service cookie is %u.", avahi_server_get_host_name_fqdn(s), avahi_server_get_local_service_cookie(s));
            sd_notifyf(0, "STATUS=Server startup complete. Host name is %s. Local service cookie is %u.", avahi_server_get_host_name_fqdn(s), avahi_server_get_local_service_cookie(s));
            avahi_set_proc_title(argv0, "%s: running [%s]", argv0, avahi_server_get_host_name_fqdn(s));

            static_service_add_to_server();
            static_hosts_add_to_server();

            remove_dns_server_entry_groups();

            if (c->publish_resolv_conf && resolv_conf_name_servers && resolv_conf_name_servers[0])
                resolv_conf_entry_group = add_dns_servers(s, resolv_conf_entry_group, resolv_conf_name_servers);

            if (c->publish_dns_servers && c->publish_dns_servers[0])
                dns_servers_entry_group = add_dns_servers(s, dns_servers_entry_group, c->publish_dns_servers);

            simple_protocol_restart_queries();
            break;

        case AVAHI_SERVER_COLLISION: {
            char *n;

            static_service_remove_from_server();
            static_hosts_remove_from_server();
            remove_dns_server_entry_groups();

            n = avahi_alternative_host_name(avahi_server_get_host_name(s));

            avahi_log_warn("Host name conflict, retrying with %s", n);
            sd_notifyf(0, "STATUS=Host name conflict, retrying with %s", n);
            avahi_set_proc_title(argv0, "%s: collision [%s]", argv0, n);

            avahi_server_set_host_name(s, n);
            avahi_free(n);

            break;
        }

        case AVAHI_SERVER_FAILURE:

            avahi_log_error("Server error: %s", avahi_strerror(avahi_server_errno(s)));
            sd_notifyf(0, "STATUS=Server error: %s", avahi_strerror(avahi_server_errno(s)));

            avahi_simple_poll_quit(simple_poll_api);
            break;

        case AVAHI_SERVER_REGISTERING:

            sd_notifyf(0, "STATUS=Registering host name %s", avahi_server_get_host_name_fqdn(s));
            avahi_set_proc_title(argv0, "%s: registering [%s]", argv0, avahi_server_get_host_name_fqdn(s));

            static_service_remove_from_server();
            static_hosts_remove_from_server();
            remove_dns_server_entry_groups();

            break;

        case AVAHI_SERVER_INVALID:
            break;

    }
}
Example #18
0
int main(int argc, char *argv[]) {
    int r = 255;
    int wrote_pid_file = 0;

    avahi_set_log_function(log_function);

    init_rand_seed();

    avahi_server_config_init(&config.server_config);
    config.command = DAEMON_RUN;
    config.daemonize = 0;
    config.config_file = NULL;
#ifdef HAVE_DBUS
    config.enable_dbus = 1;
    config.fail_on_missing_dbus = 1;
    config.n_clients_max = 0;
    config.n_objects_per_client_max = 0;
    config.n_entries_per_entry_group_max = 0;
#endif

    config.drop_root = 1;
    config.set_rlimits = 1;
#ifdef ENABLE_CHROOT
    config.use_chroot = 1;
#endif
    config.modify_proc_title = 1;

    config.disable_user_service_publishing = 0;
    config.publish_dns_servers = NULL;
    config.publish_resolv_conf = 0;
    config.use_syslog = 0;
    config.debug = 0;
    config.rlimit_as_set = 0;
    config.rlimit_core_set = 0;
    config.rlimit_data_set = 0;
    config.rlimit_fsize_set = 0;
    config.rlimit_nofile_set = 0;
    config.rlimit_stack_set = 0;
#ifdef RLIMIT_NPROC
    config.rlimit_nproc_set = 0;
#endif

    if ((argv0 = strrchr(argv[0], '/')))
        argv0 = avahi_strdup(argv0 + 1);
    else
        argv0 = avahi_strdup(argv[0]);

    daemon_pid_file_ident = (const char *) argv0;
    daemon_log_ident = (char*) argv0;
    daemon_pid_file_proc = pid_file_proc;

    if (parse_command_line(&config, argc, argv) < 0)
        goto finish;

    if (config.modify_proc_title)
        avahi_init_proc_title(argc, argv);

#ifdef ENABLE_CHROOT
    config.use_chroot = config.use_chroot && config.drop_root;
#endif

    if (config.command == DAEMON_HELP) {
        help(stdout);
        r = 0;
    } else if (config.command == DAEMON_VERSION) {
        printf("%s "PACKAGE_VERSION"\n", argv0);
        r = 0;
    } else if (config.command == DAEMON_KILL) {
        if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
            avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
            goto finish;
        }

        r = 0;

    } else if (config.command == DAEMON_RELOAD) {
        if (daemon_pid_file_kill(SIGHUP) < 0) {
            avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
            goto finish;
        }

        r = 0;

    } else if (config.command == DAEMON_CHECK)
        r = (daemon_pid_file_is_running() >= 0) ? 0 : 1;
    else if (config.command == DAEMON_RUN) {
        pid_t pid;

        if (getuid() != 0 && config.drop_root) {
            avahi_log_error("This program is intended to be run as root.");
            goto finish;
        }

        if ((pid = daemon_pid_file_is_running()) >= 0) {
            avahi_log_error("Daemon already running on PID %u", pid);
            goto finish;
        }

        if (load_config_file(&config) < 0)
            goto finish;

        if (config.daemonize) {
            daemon_retval_init();

            if ((pid = daemon_fork()) < 0)
                goto finish;
            else if (pid != 0) {
                int ret;
                /** Parent **/

                if ((ret = daemon_retval_wait(20)) < 0) {
                    avahi_log_error("Could not receive return value from daemon process.");
                    goto finish;
                }

                r = ret;
                goto finish;
            }

            /* Child */
        }

        if (config.use_syslog || config.daemonize)
            daemon_log_use = DAEMON_LOG_SYSLOG;

        if (sd_listen_fds(0) <= 0)
            if (daemon_close_all(-1) < 0)
                avahi_log_warn("Failed to close all remaining file descriptors: %s", strerror(errno));

        daemon_reset_sigs(-1);
        daemon_unblock_sigs(-1);

        if (make_runtime_dir() < 0)
            goto finish;

        if (config.drop_root) {
#ifdef ENABLE_CHROOT
            if (config.use_chroot)
                if (avahi_caps_reduce() < 0)
                    goto finish;
#endif

            if (drop_root() < 0)
                goto finish;

#ifdef ENABLE_CHROOT
            if (config.use_chroot)
                if (avahi_caps_reduce2() < 0)
                    goto finish;
#endif
        }

        if (daemon_pid_file_create() < 0) {
            avahi_log_error("Failed to create PID file: %s", strerror(errno));

            if (config.daemonize)
                daemon_retval_send(1);
            goto finish;
        } else
            wrote_pid_file = 1;

        if (config.set_rlimits)
            enforce_rlimits();

        chdir("/");

#ifdef ENABLE_CHROOT
        if (config.drop_root && config.use_chroot)
            if (avahi_chroot_helper_start(argv0) < 0) {
                avahi_log_error("failed to start chroot() helper daemon.");
                goto finish;
            }
#endif
        avahi_log_info("%s "PACKAGE_VERSION" starting up.", argv0);
        sd_notifyf(0, "STATUS=%s "PACKAGE_VERSION" starting up.", argv0);
        avahi_set_proc_title(argv0, "%s: starting up", argv0);

        if (run_server(&config) == 0)
            r = 0;

        avahi_log_info("%s "PACKAGE_VERSION" exiting.", argv0);
        sd_notifyf(0, "STATUS=%s "PACKAGE_VERSION" exiting.", argv0);
    }

finish:

    if (config.daemonize)
        daemon_retval_done();

    avahi_server_config_free(&config.server_config);
    avahi_free(config.config_file);
    avahi_strfreev(config.publish_dns_servers);
    avahi_strfreev(resolv_conf_name_servers);
    avahi_strfreev(resolv_conf_search_domains);

    if (wrote_pid_file) {
#ifdef ENABLE_CHROOT
        avahi_chroot_helper_unlink(pid_file_proc());
#else
        daemon_pid_file_remove();
#endif
    }

#ifdef ENABLE_CHROOT
    avahi_chroot_helper_shutdown();
#endif

    avahi_free(argv0);

    return r;
}
Example #19
0
bool XzeroDaemon::setup(std::istream *settings, const std::string& filename, int optimizationLevel)
{
    TRACE("setup(%s)", filename.c_str());

    runner_->setErrorHandler(std::bind(&wrap_log_error, this, "parser", std::placeholders::_1));
    runner_->setOptimizationLevel(optimizationLevel);

    if (!runner_->open(filename, settings)) {
        sd_notifyf(0, "ERRNO=%d", errno);
        goto err;
    }

    if (!validateConfig())
        goto err;

    // run setup
    TRACE("run 'setup'");
    if (runner_->invoke(runner_->findHandler("setup")))
        goto err;

    // grap the request handler
    TRACE("get pointer to 'main'");

    {
        bool (*main)(void*);
        main = runner_->getPointerTo(runner_->findHandler("main"));

        if (!main)
            goto err;

        server_->requestHandler = main;
    }

    // {{{ setup server-tag
    {
#if defined(HAVE_SYS_UTSNAME_H)
        {
            utsname utsname;
            if (uname(&utsname) == 0) {
                addComponent(std::string(utsname.sysname) + "/" + utsname.release);
                addComponent(utsname.machine);
            }
        }
#endif

#if defined(HAVE_BZLIB_H)
        {
            std::string zver("bzip2/");
            zver += BZ2_bzlibVersion();
            zver = zver.substr(0, zver.find(","));
            addComponent(zver);
        }
#endif

#if defined(HAVE_ZLIB_H)
        {
            std::string zver("zlib/");
            zver += zlib_version;
            addComponent(zver);
        }
#endif

        Buffer tagbuf;
        tagbuf.push_back("x0/" VERSION);

        if (!components_.empty())
        {
            tagbuf.push_back(" (");

            for (int i = 0, e = components_.size(); i != e; ++i)
            {
                if (i)
                    tagbuf.push_back(", ");

                tagbuf.push_back(components_[i]);
            }

            tagbuf.push_back(")");
        }
        server_->tag = tagbuf.str();
    }
    // }}}

    // {{{ run post-config hooks
    TRACE("setup: post_config");
    for (auto i: plugins_)
        if (!i->post_config())
            goto err;
    // }}}

    // {{{ run post-check hooks
    TRACE("setup: post_check");
    for (auto i: plugins_)
        if (!i->post_check())
            goto err;
    // }}}

    // {{{ check for available TCP listeners
    if (server_->listeners().empty()) {
        log(Severity::error, "No HTTP listeners defined");
        goto err;
    }
    for (auto i: server_->listeners())
        if (!i->isOpen())
            goto err;
    // }}}

    // {{{ check for SO_REUSEPORT feature in TCP listeners
    if (server_->workers().size() == 1) {
        // fast-path scheduling for single-threaded mode
        server_->workers().front()->bind(server_->listeners().front());
    } else {
        std::list<ServerSocket*> dups;
        for (auto listener: server_->listeners()) {
            if (listener->reusePort()) {
                for (auto worker: server_->workers()) {
                    if (worker->id() > 0) {
                        // clone listener for non-main worker
                        listener = listener->clone(worker->loop());
                        dups.push_back(listener);
                    }
                    worker->bind(listener);
                }
            }
        }

        // FIXME: this is not yet well thought.
        // - how to handle configuration file reloads wrt SO_REUSEPORT?
        for (auto dup: dups) {
            server_->listeners().push_back(dup);
        }
    }
    // }}}

    // {{{ x0d: check for superfluous passed file descriptors (and close them)
    for (auto fd: ServerSocket::getInheritedSocketList()) {
        bool found = false;
        for (auto li: server_->listeners()) {
            if (fd == li->handle()) {
                found = true;
                break;
            }
        }
        if (!found) {
            log(Severity::debug, "Closing inherited superfluous listening socket %d.", fd);
            ::close(fd);
        }
    }
    // }}}

    // {{{ systemd: check for superfluous passed file descriptors
    if (int count = sd_listen_fds(0)) {
        int maxfd = SD_LISTEN_FDS_START + count;
        count = 0;
        for (int fd = SD_LISTEN_FDS_START; fd < maxfd; ++fd) {
            bool found = false;
            for (auto li: server_->listeners()) {
                if (fd == li->handle()) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                ++count;
            }
        }
        if (count) {
            fprintf(stderr, "superfluous systemd file descriptors: %d\n", count);
            return false;
        }
    }
    // }}}

    // XXX post worker wakeup
    // we do an explicit wakeup of all workers here since there might be already
    // some (configure-time related) events pending, i.e. director's (fcgi) health checker
    // FIXME this is more a workaround than a fix.
    for (auto worker: server_->workers())
        worker->wakeup();

    TRACE("setup: done.");
    return true;

err:
    return false;
}
Example #20
0
File: epmd_srv.c Project: RJ/otp
void run(EpmdVars *g)
{
  struct EPMD_SOCKADDR_IN iserv_addr[MAX_LISTEN_SOCKETS];
  int listensock[MAX_LISTEN_SOCKETS];
  int num_sockets;
  int i;
  int opt;
  unsigned short sport = g->port;

  node_init(g);
  g->conn = conn_init(g);

#ifdef HAVE_SYSTEMD_DAEMON
  if (g->is_systemd)
    {
      int n;
      
      dbg_printf(g,2,"try to obtain sockets from systemd");

      n = sd_listen_fds(0);
      if (n < 0)
        {
          dbg_perror(g,"cannot obtain sockets from systemd");
          epmd_cleanup_exit(g,1);
        }
      else if (n == 0)
        {
          dbg_tty_printf(g,0,"systemd provides no sockets");
          epmd_cleanup_exit(g,1);
      }
      else if (n > MAX_LISTEN_SOCKETS)
      {
          dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses", MAX_LISTEN_SOCKETS);
          epmd_cleanup_exit(g,1);
      } 
      num_sockets = n;
      for (i = 0; i < num_sockets; i++)
        {
          g->listenfd[i] = listensock[i] = SD_LISTEN_FDS_START + i;
        }
    }
  else
    {
#endif /* HAVE_SYSTEMD_DAEMON */

  dbg_printf(g,2,"try to initiate listening port %d", g->port);

  if (g->addresses != NULL && /* String contains non-separator characters if: */
      g->addresses[strspn(g->addresses," ,")] != '\000')
    {
      char *tmp;
      char *token;
      int loopback_ok = 0;

      if ((tmp = (char *)malloc(strlen(g->addresses) + 1)) == NULL)
	{
	  dbg_perror(g,"cannot allocate memory");
	  epmd_cleanup_exit(g,1);
	}
      strcpy(tmp,g->addresses);

      for(token = strtok(tmp,", "), num_sockets = 0;
	  token != NULL;
	  token = strtok(NULL,", "), num_sockets++)
	{
	  struct EPMD_IN_ADDR addr;
#ifdef HAVE_INET_PTON
	  int ret;

	  if ((ret = inet_pton(FAMILY,token,&addr)) == -1)
	    {
	      dbg_perror(g,"cannot convert IP address to network format");
	      epmd_cleanup_exit(g,1);
	    }
	  else if (ret == 0)
#elif !defined(EPMD6)
	  if ((addr.EPMD_S_ADDR = inet_addr(token)) == INADDR_NONE)
#endif
	    {
	      dbg_tty_printf(g,0,"cannot parse IP address \"%s\"",token);
	      epmd_cleanup_exit(g,1);
	    }

	  if (IS_ADDR_LOOPBACK(addr))
	    loopback_ok = 1;

	  if (num_sockets - loopback_ok == MAX_LISTEN_SOCKETS - 1)
	    {
	      dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses",
			     MAX_LISTEN_SOCKETS);
	      epmd_cleanup_exit(g,1);
	    }

	  SET_ADDR(iserv_addr[num_sockets],addr.EPMD_S_ADDR,sport);
	}

      free(tmp);

      if (!loopback_ok)
	{
	  SET_ADDR(iserv_addr[num_sockets],EPMD_ADDR_LOOPBACK,sport);
	  num_sockets++;
	}
    }
  else
    {
      SET_ADDR(iserv_addr[0],EPMD_ADDR_ANY,sport);
      num_sockets = 1;
    }
#ifdef HAVE_SYSTEMD_DAEMON
    }
#endif /* HAVE_SYSTEMD_DAEMON */

#if !defined(__WIN32__)
  /* We ignore the SIGPIPE signal that is raised when we call write
     twice on a socket closed by the other end. */
  signal(SIGPIPE, SIG_IGN);
#endif

  /*
   * Initialize number of active file descriptors.
   * Stdin, stdout, and stderr are still open.
   */
  g->active_conn = 3 + num_sockets;
  g->max_conn -= num_sockets;

  FD_ZERO(&g->orig_read_mask);
  g->select_fd_top = 0;

#ifdef HAVE_SYSTEMD_DAEMON
  if (g->is_systemd)
      for (i = 0; i < num_sockets; i++)
          select_fd_set(g, listensock[i]);
  else
    {
#endif /* HAVE_SYSTEMD_DAEMON */
  for (i = 0; i < num_sockets; i++)
    {
      if ((listensock[i] = socket(FAMILY,SOCK_STREAM,0)) < 0)
	{
	  dbg_perror(g,"error opening stream socket");
	  epmd_cleanup_exit(g,1);
	}
      g->listenfd[i] = listensock[i];
  
      /*
       * Note that we must not enable the SO_REUSEADDR on Windows,
       * because addresses will be reused even if they are still in use.
       */
  
#if !defined(__WIN32__)
      opt = 1;
      if (setsockopt(listensock[i],SOL_SOCKET,SO_REUSEADDR,(char* ) &opt,
		     sizeof(opt)) <0)
	{
	  dbg_perror(g,"can't set sockopt");
	  epmd_cleanup_exit(g,1);
	}
#endif
  
      /* In rare cases select returns because there is someone
	 to accept but the request is withdrawn before the
	 accept function is called. We set the listen socket
	 to be non blocking to prevent us from being hanging
	 in accept() waiting for the next request. */
#if (defined(__WIN32__) || defined(NO_FCNTL))
      opt = 1;
      /* Gives warning in VxWorks */
      if (ioctl(listensock[i], FIONBIO, &opt) != 0)
#else
      opt = fcntl(listensock[i], F_GETFL, 0);
      if (fcntl(listensock[i], F_SETFL, opt | O_NONBLOCK) == -1)
#endif /* __WIN32__ || VXWORKS */
	dbg_perror(g,"failed to set non-blocking mode of listening socket %d",
		   listensock[i]);

      if (bind(listensock[i], (struct sockaddr*) &iserv_addr[i],
	  sizeof(iserv_addr[i])) < 0)
	{
	  if (errno == EADDRINUSE)
	    {
	      dbg_tty_printf(g,1,"there is already a epmd running at port %d",
			     g->port);
	      epmd_cleanup_exit(g,0);
	    }
	  else
	    {
	      dbg_perror(g,"failed to bind socket");
	      epmd_cleanup_exit(g,1);
	    }
	}

      if(listen(listensock[i], SOMAXCONN) < 0) {
          dbg_perror(g,"failed to listen on socket");
          epmd_cleanup_exit(g,1);
      }
      select_fd_set(g, listensock[i]);
    }
#ifdef HAVE_SYSTEMD_DAEMON
    }
    sd_notifyf(0, "READY=1\n"
                  "STATUS=Processing port mapping requests...\n"
                  "MAINPID=%lu", (unsigned long) getpid());
#endif /* HAVE_SYSTEMD_DAEMON */

  dbg_tty_printf(g,2,"entering the main select() loop");

 select_again:
  while(1)
    {
      fd_set read_mask = g->orig_read_mask;
      struct timeval timeout;
      int ret;

      /* If we are idle we time out now and then to enable the code
	 below to close connections that are old and probably
	 hanging. Make sure that select will return often enough. */

      timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT;
      timeout.tv_usec = 0;

      if ((ret = select(g->select_fd_top,
			&read_mask, (fd_set *)0,(fd_set *)0,&timeout)) < 0) {
	dbg_perror(g,"error in select ");
        switch (errno) {
          case EAGAIN:
          case EINTR:
            break;
          default:
            epmd_cleanup_exit(g,1);
        }
      }
      else {
	time_t now;
	if (ret == 0) {
	  FD_ZERO(&read_mask);
	}
	if (g->delay_accept) {		/* Test of busy server */
	  sleep(g->delay_accept);
	}

	for (i = 0; i < num_sockets; i++)
	  if (FD_ISSET(listensock[i],&read_mask)) {
	    if (do_accept(g, listensock[i]) && g->active_conn < g->max_conn) {
	      /*
	       * The accept() succeeded, and we have at least one file
	       * descriptor still free, which means that another accept()
	       * could succeed. Go do do another select(), in case there
	       * are more incoming connections waiting to be accepted.
	       */
	      goto select_again;
	    }
	  }
	  
	/* Check all open streams marked by select for data or a
	   close.  We also close all open sockets except ALIVE
	   with no activity for a long period */

	now = current_time(g);
	for (i = 0; i < g->max_conn; i++) {
	  if (g->conn[i].open == EPMD_TRUE) {
	    if (FD_ISSET(g->conn[i].fd,&read_mask))
	      do_read(g,&g->conn[i]);
	    else if ((g->conn[i].keep == EPMD_FALSE) &&
		     ((g->conn[i].mod_time + g->packet_timeout) < now)) {
	      dbg_tty_printf(g,1,"closing because timed out on receive");
	      epmd_conn_close(g,&g->conn[i]);
	    }
	  }
	}
      }
    }
}
Example #21
0
static int rename_service(sd_bus *a, sd_bus *b) {
        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
        _cleanup_free_ char *p = NULL, *name = NULL;
        const char *comm;
        char **cmdline;
        uid_t uid;
        pid_t pid;
        int r;

        assert(a);
        assert(b);

        r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
        if (r < 0)
                return r;

        r = sd_bus_creds_get_euid(creds, &uid);
        if (r < 0)
                return r;

        r = sd_bus_creds_get_pid(creds, &pid);
        if (r < 0)
                return r;

        r = sd_bus_creds_get_cmdline(creds, &cmdline);
        if (r < 0)
                return r;

        r = sd_bus_creds_get_comm(creds, &comm);
        if (r < 0)
                return r;

        name = uid_to_name(uid);
        if (!name)
                return -ENOMEM;

        p = strv_join(cmdline, " ");
        if (!p)
                return -ENOMEM;

        /* The status string gets the full command line ... */
        sd_notifyf(false,
                   "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
                   pid, p,
                   uid, name);

        /* ... and the argv line only the short comm */
        if (arg_command_line_buffer) {
                size_t m, w;

                m = strlen(arg_command_line_buffer);
                w = snprintf(arg_command_line_buffer, m,
                             "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
                             pid, comm,
                             uid, name);

                if (m > w)
                        memzero(arg_command_line_buffer + w, m - w);
        }

        log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
                  pid, p,
                  uid, name,
                  a->unique_name);

        return 0;
}
Example #22
0
File: main.c Project: CoiLock/uhub
int main_loop()
{
	struct hub_config configuration;
	struct acl_handle acl;
	struct hub_info* hub = 0;

	if (net_initialize() == -1)
		return -1;

	do
	{
		if (hub)
		{
			LOG_INFO("Reloading configuration files...");
			LOG_DEBUG("Hub status: %d", (int) hub->status);

			/* Reinitialize logs */
			hub_log_shutdown();
			hub_log_initialize(arg_log, arg_log_syslog);
			hub_set_log_verbosity(arg_verbose);
		}

		if (read_config(arg_config, &configuration, !arg_have_config) == -1)
			return -1;

		if (acl_initialize(&configuration, &acl) == -1)
			return -1;

		/*
		 * Don't restart networking when re-reading configuration.
		 * This might not be possible either, since we might have
		 * dropped our privileges to do so.
		 */
		if (!hub)
		{
			hub = hub_start_service(&configuration);
			if (!hub)
			{
				acl_shutdown(&acl);
				free_config(&configuration);
				net_destroy();
				hub_log_shutdown();
				return -1;
			}
#if !defined(WIN32)
			setup_signal_handlers(hub);
#ifdef SYSTEMD
                        /* Notify the service manager that this daemon has
                         * been successfully initalized and shall enter the
                         * main loop.
                         */
                        sd_notifyf(0, "READY=1\n"
                                      "MAINPID=%lu", (unsigned long) getpid());
#endif /* SYSTEMD */

#endif /* ! WIN32 */
		}

		hub_set_variables(hub, &acl);

		hub_event_loop(hub);

		hub_free_variables(hub);
		acl_shutdown(&acl);
		free_config(&configuration);

	} while (hub->status == hub_status_restart);

#if !defined(WIN32)
	shutdown_signal_handlers(hub);
#endif

	if (hub)
	{
		hub_shutdown_service(hub);
	}

	net_destroy();
	hub_log_shutdown();
	return 0;
}
Example #23
0
int manager_connect(Manager *m) {
        int r;

        assert(m);

        manager_disconnect(m);

        m->event_retry = sd_event_source_unref(m->event_retry);
        if (!ratelimit_test(&m->ratelimit)) {
                log_debug("Slowing down attempts to contact servers.");

                r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m);
                if (r < 0) {
                        log_error("Failed to create retry timer: %s", strerror(-r));
                        return r;
                }

                return 0;
        }

        /* If we already are operating on some address, switch to the
         * next one. */
        if (m->current_server_address && m->current_server_address->addresses_next)
                manager_set_server_address(m, m->current_server_address->addresses_next);
        else {
                struct addrinfo hints = {
                        .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
                        .ai_socktype = SOCK_DGRAM,
                };

                /* Hmm, we are through all addresses, let's look for the next host instead */
                if (m->current_server_name && m->current_server_name->names_next)
                        manager_set_server_name(m, m->current_server_name->names_next);
                else {
                        ServerName *f;

                        /* Our current server name list is exhausted,
                         * let's find the next one to iterate. First
                         * we try the system list, then the link list.
                         * After having processed the link list we
                         * jump back to the system list. However, if
                         * both lists are empty, we change to the
                         * fallback list. */
                        if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) {
                                f = m->system_servers;
                                if (!f)
                                        f = m->link_servers;
                        } else {
                                f = m->link_servers;
                                if (!f)
                                        f = m->system_servers;
                        }

                        if (!f)
                                f = m->fallback_servers;

                        if (!f) {
                                manager_set_server_name(m, NULL);
                                log_debug("No server found.");
                                return 0;
                        }

                        manager_set_server_name(m, f);
                }

                /* Tell the resolver to reread /etc/resolv.conf, in
                 * case it changed. */
                res_init();

                /* Flush out any previously resolved addresses */
                server_name_flush_addresses(m->current_server_name);

                log_debug("Resolving %s...", m->current_server_name->string);

                r = sd_resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, m);
                if (r < 0) {
                        log_error("Failed to create resolver: %s", strerror(-r));
                        return r;
                }

                return 1;
        }

        r = manager_begin(m);
        if (r < 0)
                return r;

        return 1;
}

void manager_disconnect(Manager *m) {
        assert(m);

        m->resolve_query = sd_resolve_query_unref(m->resolve_query);

        m->event_timer = sd_event_source_unref(m->event_timer);

        m->event_receive = sd_event_source_unref(m->event_receive);
        m->server_socket = safe_close(m->server_socket);

        m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
        m->clock_watch_fd = safe_close(m->clock_watch_fd);

        m->event_timeout = sd_event_source_unref(m->event_timeout);

        sd_notifyf(false, "STATUS=Idle.");
}
Example #24
0
ScreenToVnc::ScreenToVnc(QObject *parent) :
    QObject(parent)
{
    IN;
    // TODO: make that configurable?
    exitWhenLastClientGone = false;
    isEmptyMouse = false;
    m_fbfd = -1;
    lastPointerEvent = QDateTime::currentMSecsSinceEpoch();
    lastPointerMove = lastPointerEvent;

    // Unix Signal Handling set up
    if (::socketpair(AF_UNIX, SOCK_STREAM, 0, unixHupSignalFd))
        qFatal("Couldn't create HUP socketpair");

    if (::socketpair(AF_UNIX, SOCK_STREAM, 0, unixTermSignalFd))
        qFatal("Couldn't create TERM socketpair");

    hupSignalNotifier = new QSocketNotifier(unixHupSignalFd[1], QSocketNotifier::Read, this);
    connect(hupSignalNotifier,
            SIGNAL(activated(int)),
            this,
            SLOT(qtHubSignalHandler()));

    termSignalNotifier = new QSocketNotifier(unixTermSignalFd[1], QSocketNotifier::Read, this);
    connect(termSignalNotifier,
            SIGNAL(activated(int)),
            this,
            SLOT(qtTermSignalHandler()));

    // init the Framebuffer
    init_fb();

    // setup vnc server
    // must run after init_rb, so m_scrinfo and m_xPadding is set!
    char *argv[0];
    m_server = rfbGetScreen(0,argv,(m_scrinfo.xres + m_xPadding), m_scrinfo.yres, 8, 3, m_scrinfo.bits_per_pixel / 8);

    if(!m_server){
        LOG() << "failed to create VNC server";
    }

    m_server->desktopName = "Mer VNC";
    m_server->frameBuffer=(char*)malloc((m_scrinfo.xres + m_xPadding)*m_scrinfo.yres*(m_scrinfo.bits_per_pixel / 8));
    m_server->alwaysShared=(1==1);

    m_server->newClientHook = newclient;
    m_server->ptrAddEvent = mouseHandler;

    // check if launched by systemd with a ready socket (LISTEN_FDS env var)
    int sd_fds = sd_listen_fds(1);
    if (sd_fds){
        for (int i = SD_LISTEN_FDS_START; i <= (SD_LISTEN_FDS_START + sd_fds - 1); i++){
            if (sd_is_socket(i, AF_INET6, SOCK_STREAM, 1)
                || sd_is_socket(i, AF_INET, SOCK_STREAM, 1)){
                LOG() << "using given socket at FD:" << i;
                m_server->autoPort = false;
                m_server->port = 0;
                m_server->ipv6port = 0;
                m_server->udpPort = 0;
                m_server->listenSock = i;
                FD_SET(m_server->listenSock, &(m_server->allFds));
                m_server->maxFd = m_server->listenSock;
                exitWhenLastClientGone = true;
            }
        }
    }

    // init the cursors
    init_fingerPointers();
    makeRichCursor(m_server);

    // Initialize the VNC server
    rfbInitServer(m_server);

    // init compare frame buffer
    m_compareFrameBuffer = (unsigned short int *)calloc((m_scrinfo.xres + m_xPadding) * m_scrinfo.yres, (m_scrinfo.bits_per_pixel / 8));

    m_screenshotTimer = new QTimer(this);
    connect(m_screenshotTimer,
            SIGNAL(timeout()),
            this,
            SLOT(grapFrame()));

    m_processTimer = new QTimer(this);
    connect(m_processTimer,
            SIGNAL(timeout()),
            this,
            SLOT(rfbProcessTrigger()));

    // open the event device
    // TODO: not Hardcode?
    eventDev = open("/dev/input/event0", O_RDWR);
    if(eventDev < 0) {
        LOG() << "can't open /dev/input/event0";
        return;
    }

    // start the process trigger timers
    m_processTimer->start();
    m_screenshotTimer->start(300);

    // inform systemd that we started up
    sd_notifyf(0, "READY=1\n"
               "STATUS=Processing requests...\n"
               "MAINPID=%lu",
               (unsigned long) getpid());

    OUT;
}
Example #25
0
int main(int argc, char *argv[]) {
        enum {
                FD_SOCKET,
                FD_WALL_TIMER,
                FD_NOLOGIN_TIMER,
                FD_SHUTDOWN_TIMER,
                _FD_MAX
        };

        int r = EXIT_FAILURE, n_fds;
        int one = 1;
        struct shutdownd_command c;
        struct pollfd pollfd[_FD_MAX];
        bool exec_shutdown = false, unlink_nologin = false, failed = false;
        unsigned i;

        if (getppid() != 1) {
                log_error("This program should be invoked by init only.");
                return EXIT_FAILURE;
        }

        if (argc > 1) {
                log_error("This program does not take arguments.");
                return EXIT_FAILURE;
        }

        log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
        log_parse_environment();
        log_open();

        if ((n_fds = sd_listen_fds(true)) < 0) {
                log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
                return EXIT_FAILURE;
        }

        if (n_fds != 1) {
                log_error("Need exactly one file descriptor.");
                return EXIT_FAILURE;
        }

        if (setsockopt(SD_LISTEN_FDS_START, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
                log_error("SO_PASSCRED failed: %m");
                return EXIT_FAILURE;
        }

        zero(c);
        zero(pollfd);

        pollfd[FD_SOCKET].fd = SD_LISTEN_FDS_START;
        pollfd[FD_SOCKET].events = POLLIN;

        for (i = 0; i < _FD_MAX; i++) {

                if (i == FD_SOCKET)
                        continue;

                pollfd[i].events = POLLIN;

                if ((pollfd[i].fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
                        log_error("timerfd_create(): %m");
                        failed = true;
                }
        }

        if (failed)
                goto finish;

        log_debug("systemd-shutdownd running as pid %lu", (unsigned long) getpid());

        sd_notify(false,
                  "READY=1\n"
                  "STATUS=Processing requests...");

        do {
                int k;
                usec_t n;

                if (poll(pollfd, _FD_MAX, -1) < 0) {

                        if (errno == EAGAIN || errno == EINTR)
                                continue;

                        log_error("poll(): %m");
                        goto finish;
                }

                n = now(CLOCK_REALTIME);

                if (pollfd[FD_SOCKET].revents) {

                        if ((k = read_packet(pollfd[FD_SOCKET].fd, &c)) < 0)
                                goto finish;
                        else if (k > 0 && c.elapse > 0) {
                                struct itimerspec its;
                                char date[FORMAT_TIMESTAMP_MAX];

                                if (c.warn_wall) {
                                        /* Send wall messages every so often */
                                        zero(its);
                                        timespec_store(&its.it_value, when_wall(n, c.elapse));
                                        if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                                log_error("timerfd_settime(): %m");
                                                goto finish;
                                        }

                                        /* Warn immediately if less than 15 minutes are left */
                                        if (n < c.elapse &&
                                            n + 15*USEC_PER_MINUTE >= c.elapse)
                                                warn_wall(n, &c);
                                }

                                /* Disallow logins 5 minutes prior to shutdown */
                                zero(its);
                                timespec_store(&its.it_value, when_nologin(c.elapse));
                                if (timerfd_settime(pollfd[FD_NOLOGIN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                        log_error("timerfd_settime(): %m");
                                        goto finish;
                                }

                                /* Shutdown after the specified time is reached */
                                zero(its);
                                timespec_store(&its.it_value, c.elapse);
                                if (timerfd_settime(pollfd[FD_SHUTDOWN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                        log_error("timerfd_settime(): %m");
                                        goto finish;
                                }

                                sd_notifyf(false,
                                           "STATUS=Shutting down at %s...",
                                           format_timestamp(date, sizeof(date), c.elapse));
                        }
                }

                if (pollfd[FD_WALL_TIMER].revents) {
                        struct itimerspec its;

                        warn_wall(n, &c);
                        flush_fd(pollfd[FD_WALL_TIMER].fd);

                        /* Restart timer */
                        zero(its);
                        timespec_store(&its.it_value, when_wall(n, c.elapse));
                        if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
                                log_error("timerfd_settime(): %m");
                                goto finish;
                        }
                }

                if (pollfd[FD_NOLOGIN_TIMER].revents) {
                        int e;

                        log_info("Creating /run/nologin, blocking further logins...");

                        if ((e = write_one_line_file("/run/nologin", "System is going down.")) < 0)
                                log_error("Failed to create /run/nologin: %s", strerror(-e));
                        else
                                unlink_nologin = true;

                        flush_fd(pollfd[FD_NOLOGIN_TIMER].fd);
                }

                if (pollfd[FD_SHUTDOWN_TIMER].revents) {
                        exec_shutdown = true;
                        goto finish;
                }

        } while (c.elapse > 0);

        r = EXIT_SUCCESS;

        log_debug("systemd-shutdownd stopped as pid %lu", (unsigned long) getpid());

finish:

        for (i = 0; i < _FD_MAX; i++)
                if (pollfd[i].fd >= 0)
                        close_nointr_nofail(pollfd[i].fd);

        if (unlink_nologin)
                unlink("/run/nologin");

        if (exec_shutdown) {
                char sw[3];

                sw[0] = '-';
                sw[1] = c.mode;
                sw[2] = 0;

                execl(SYSTEMCTL_BINARY_PATH,
                      "shutdown",
                      sw,
                      "now",
                      (c.warn_wall && c.wall_message[0]) ? c.wall_message :
                      (c.warn_wall ? NULL : "--no-wall"),
                      NULL);

                log_error("Failed to execute /sbin/shutdown: %m");
        }

        sd_notify(false,
                  "STATUS=Exiting...");

        return r;
}
Example #26
0
void notifyStatus(const QString &status)
{
	sd_notifyf(0, "STATUS=%s", status.toLocal8Bit().constData());
}
Example #27
0
bool XzeroDaemon::setup(std::unique_ptr<std::istream>&& settings, const std::string& filename, int optimizationLevel)
{
	TRACE(1, "setup(%s)", filename.c_str());

    FlowParser parser(this);
    parser.importHandler = std::bind(&XzeroDaemon::import, this, std::placeholders::_1, std::placeholders::_2,
            std::placeholders::_3);

    if (!parser.open(filename, std::move(settings))) {
        sd_notifyf(0, "ERRNO=%d", errno);
        fprintf(stderr, "Failed to open file: %s\n", filename.c_str());
        return false;
    }

	unit_ = parser.parse();
    if (!unit_)
        return false;

    if (dumpAST_)
        ASTPrinter::print(unit_.get());

    std::unique_ptr<IRProgram> ir = IRGenerator::generate(unit_.get());
    if (!ir) {
        fprintf(stderr, "IR generation failed. Aborting.\n");
        return false;
    }

    {
        PassManager pm;

        // mandatory passes
        pm.registerPass(std::make_unique<UnusedBlockPass>());

        // optional passes
        if (optimizationLevel >= 1) {
            pm.registerPass(std::make_unique<EmptyBlockElimination>());
            pm.registerPass(std::make_unique<InstructionElimination>());
        }

        pm.run(ir.get());
    }

    if (dumpIR_) {
        ir->dump();
    }

    program_ = TargetCodeGenerator().generate(ir.get());

    ir.reset();

    if (!program_) {
        fprintf(stderr, "Code generation failed. Aborting.\n");
        return false;
    }

    if (!program_->link(this)) {
        fprintf(stderr, "Program linking failed. Aborting.\n");
        return false;
    }

	if (!validateConfig()) {
		return false;
    }

    if (dumpTargetCode_)
        program_->dump();

	// run setup
	TRACE(1, "run 'setup'");
    if (program_->findHandler("setup")->run(nullptr))
        // should not return true
        return false;

	// grap the request handler
	TRACE(1, "get pointer to 'main'");

    {
        auto main = program_->findHandler("main");

        server_->requestHandler = [=](x0::HttpRequest* r) {
            FlowVM::Runner* cx = static_cast<FlowVM::Runner*>(r->setCustomData(r, main->createRunner()));
            cx->setUserData(r);
            bool handled = cx->run();
            if (!cx->isSuspended() && !handled) {
                r->finish();
            }
        };
    }

	// {{{ setup server-tag
	{
#if defined(HAVE_SYS_UTSNAME_H)
		{
			utsname utsname;
			if (uname(&utsname) == 0) {
				addComponent(std::string(utsname.sysname) + "/" + utsname.release);
				addComponent(utsname.machine);
			}
		}
#endif

#if defined(HAVE_BZLIB_H)
		{
			std::string zver("bzip2/");
			zver += BZ2_bzlibVersion();
			zver = zver.substr(0, zver.find(","));
			addComponent(zver);
		}
#endif

#if defined(HAVE_ZLIB_H)
		{
			std::string zver("zlib/");
			zver += zlib_version;
			addComponent(zver);
		}
#endif

		Buffer tagbuf;
		tagbuf.push_back("x0/" VERSION);

		if (!components_.empty())
		{
			tagbuf.push_back(" (");

			for (int i = 0, e = components_.size(); i != e; ++i)
			{
				if (i)
					tagbuf.push_back(", ");

				tagbuf.push_back(components_[i]);
			}

			tagbuf.push_back(")");
		}
		server_->tag = tagbuf.str();
	}
	// }}}

	// {{{ run post-config hooks
	TRACE(1, "setup: post_config");
	for (auto i: plugins_)
		if (!i->post_config())
			goto err;
	// }}}

	// {{{ run post-check hooks
	TRACE(1, "setup: post_check");
	for (auto i: plugins_)
		if (!i->post_check())
			goto err;
	// }}}

	// {{{ check for available TCP listeners
	if (server_->listeners().empty()) {
		log(Severity::error, "No HTTP listeners defined");
		goto err;
	}
	for (auto i: server_->listeners())
		if (!i->isOpen())
			goto err;
	// }}}

	// {{{ check for SO_REUSEPORT feature in TCP listeners
	if (server_->workers().size() == 1) {
		// fast-path scheduling for single-threaded mode
		server_->workers().front()->bind(server_->listeners().front());
	} else {
		std::list<ServerSocket*> dups;
		for (auto listener: server_->listeners()) {
			if (listener->reusePort()) {
				for (auto worker: server_->workers()) {
					if (worker->id() > 0) {
						// clone listener for non-main worker
						listener = listener->clone(worker->loop());
						dups.push_back(listener);
					}
					worker->bind(listener);
				}
			}
		}

		// FIXME: this is not yet well thought.
		// - how to handle configuration file reloads wrt SO_REUSEPORT?
		for (auto dup: dups) {
			server_->listeners().push_back(dup);
		}
	}
	// }}}

	// {{{ x0d: check for superfluous passed file descriptors (and close them)
	for (auto fd: ServerSocket::getInheritedSocketList()) {
		bool found = false;
		for (auto li: server_->listeners()) {
			if (fd == li->handle()) {
				found = true;
				break;
			}
		}
		if (!found) {
			log(Severity::debug, "Closing inherited superfluous listening socket %d.", fd);
			::close(fd);
		}
	}
	// }}}

	// {{{ systemd: check for superfluous passed file descriptors
	if (int count = sd_listen_fds(0)) {
		int maxfd = SD_LISTEN_FDS_START + count;
		count = 0;
		for (int fd = SD_LISTEN_FDS_START; fd < maxfd; ++fd) {
			bool found = false;
			for (auto li: server_->listeners()) {
				if (fd == li->handle()) {
					found = true;
					break;
				}
			}
			if (!found) {
				++count;
			}
		}
		if (count) {
			fprintf(stderr, "superfluous systemd file descriptors: %d\n", count);
			return false;
		}
	}
	// }}}

	// XXX post worker wakeup
	// we do an explicit wakeup of all workers here since there might be already
	// some (configure-time related) events pending, i.e. director's (fcgi) health checker
	// FIXME this is more a workaround than a fix.
	for (auto worker: server_->workers())
		worker->wakeup();

	TRACE(1, "setup: done.");
	return true;

err:
	return false;
}
Example #28
0
bool HomeApplication::run(const QString &shell)
{
    // If a compositor is already running we cannot continue
    if (Compositor::instance()->isRunning()) {
        qCWarning(GREENISLAND_COMPOSITOR) << "Compositor already running, don't call run() more than once!";
        return false;
    }

    // Set plugin
    GreenIsland::Compositor::s_fixedShell = shell;

    // Check whether XDG_RUNTIME_DIR is ok or not
    GreenIsland::verifyXdgRuntimeDir();

    // If a socket is passed it means that we are nesting into
    // another compositor, let's do some checks
    if (!m_socket.isEmpty()) {
        // We need wayland QPA plugin
        if (!QGuiApplication::platformName().startsWith(QStringLiteral("wayland"))) {
            qCWarning(GREENISLAND_COMPOSITOR)
                    << "By passing the \"--socket\" argument you are requesting to nest"
                    << "this compositor into another, but you forgot to pass "
                    << "also \"-platform wayland\"!";
#if HAVE_SYSTEMD
            if (m_notify)
                sd_notifyf(0, "STATUS=Nesting requested, but no wayland QPA");
#endif
            return false;
        }
    }

    // Screen configuration
    if (!m_fakeScreenFileName.isEmpty()) {
        // Need the native backend
        if (QGuiApplication::platformName().startsWith(QStringLiteral("wayland"))) {
            qCWarning(GREENISLAND_COMPOSITOR)
                    << "Fake screen configuration is not allowed when Green Island"
                    << "is nested into another compositor";
#if HAVE_SYSTEMD
            if (m_notify)
                sd_notifyf(0, "STATUS=Fake screen configuration not allowed when nested");
#endif
            return false;
        }
    }

    // Create the compositor
    Compositor *compositor = Compositor::instance();
    if (!m_fakeScreenFileName.isEmpty())
        compositor->setFakeScreenConfiguration(m_fakeScreenFileName);
    QObject::connect(compositor, &Compositor::screenConfigurationAcquired, [this] {
#if HAVE_SYSTEMD
        // Notify systemd when the screen configuration is ready
        if (m_notify) {
            qCDebug(GREENISLAND_COMPOSITOR) << "Compositor ready, notify systemd on" << qgetenv("NOTIFY_SOCKET");
            sd_notify(0, "READY=1");
        }
#endif
    });
    compositor->run();
    compositorLaunched();

    return true;
}
Example #29
0
static int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
        Manager *m = userdata;
        struct ntp_msg ntpmsg;

        struct iovec iov = {
                .iov_base = &ntpmsg,
                .iov_len = sizeof(ntpmsg),
        };
        union {
                struct cmsghdr cmsghdr;
                uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
        } control;
        union sockaddr_union server_addr;
        struct msghdr msghdr = {
                .msg_iov = &iov,
                .msg_iovlen = 1,
                .msg_control = &control,
                .msg_controllen = sizeof(control),
                .msg_name = &server_addr,
                .msg_namelen = sizeof(server_addr),
        };
        struct cmsghdr *cmsg;
        struct timespec now_ts;
        struct timeval *recv_time;
        ssize_t len;
        double origin, receive, trans, dest;
        double delay, offset;
        bool spike;
        int leap_sec;
        int r;

        assert(source);
        assert(m);

        if (revents & (EPOLLHUP|EPOLLERR)) {
                log_warning("Server connection returned error.");
                return manager_connect(m);
        }

        len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
        if (len < 0) {
                if (errno == EAGAIN)
                        return 0;

                log_warning("Error receiving message. Disconnecting.");
                return manager_connect(m);
        }

        if (iov.iov_len < sizeof(struct ntp_msg)) {
                log_warning("Invalid response from server. Disconnecting.");
                return manager_connect(m);
        }

        if (!m->current_server_name ||
            !m->current_server_address ||
            !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) {
                log_debug("Response from unknown server.");
                return 0;
        }

        recv_time = NULL;
        for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
                if (cmsg->cmsg_level != SOL_SOCKET)
                        continue;

                switch (cmsg->cmsg_type) {
                case SCM_TIMESTAMP:
                        recv_time = (struct timeval *) CMSG_DATA(cmsg);
                        break;
                }
        }
        if (!recv_time) {
                log_error("Invalid packet timestamp.");
                return -EINVAL;
        }

        if (!m->pending) {
                log_debug("Unexpected reply. Ignoring.");
                return 0;
        }

        /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
        if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
            be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) {
                log_debug("Invalid reply; not our transmit time. Ignoring.");
                return 0;
        }

        m->event_timeout = sd_event_source_unref(m->event_timeout);

        if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 ||
            be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) {
                log_debug("Invalid reply, returned times before epoch. Ignoring.");
                return manager_connect(m);
        }

        if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC) {
                log_debug("Server is not synchronized. Disconnecting.");
                return manager_connect(m);
        }

        if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) {
                log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field));
                return manager_connect(m);
        }

        if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) {
                log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field));
                return manager_connect(m);
        }

        /* valid packet */
        m->pending = false;
        m->retry_interval = 0;

        /* announce leap seconds */
        if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_PLUSSEC)
                leap_sec = 1;
        else if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_MINUSSEC)
                leap_sec = -1;
        else
                leap_sec = 0;

        /*
         * "Timestamp Name          ID   When Generated
         *  ------------------------------------------------------------
         *  Originate Timestamp     T1   time request sent by client
         *  Receive Timestamp       T2   time request received by server
         *  Transmit Timestamp      T3   time reply sent by server
         *  Destination Timestamp   T4   time reply received by client
         *
         *  The round-trip delay, d, and system clock offset, t, are defined as:
         *  d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2"
         */
        assert_se(clock_gettime(clock_boottime_or_monotonic(), &now_ts) >= 0);
        origin = tv_to_d(recv_time) - (ts_to_d(&now_ts) - ts_to_d(&m->trans_time_mon)) + OFFSET_1900_1970;
        receive = ntp_ts_to_d(&ntpmsg.recv_time);
        trans = ntp_ts_to_d(&ntpmsg.trans_time);
        dest = tv_to_d(recv_time) + OFFSET_1900_1970;

        offset = ((receive - origin) + (trans - dest)) / 2;
        delay = (dest - origin) - (trans - receive);

        spike = manager_sample_spike_detection(m, offset, delay);

        manager_adjust_poll(m, offset, spike);

        log_debug("NTP response:\n"
                  "  leap         : %u\n"
                  "  version      : %u\n"
                  "  mode         : %u\n"
                  "  stratum      : %u\n"
                  "  precision    : %.6f sec (%d)\n"
                  "  reference    : %.4s\n"
                  "  origin       : %.3f\n"
                  "  receive      : %.3f\n"
                  "  transmit     : %.3f\n"
                  "  dest         : %.3f\n"
                  "  offset       : %+.3f sec\n"
                  "  delay        : %+.3f sec\n"
                  "  packet count : %"PRIu64"\n"
                  "  jitter       : %.3f%s\n"
                  "  poll interval: " USEC_FMT "\n",
                  NTP_FIELD_LEAP(ntpmsg.field),
                  NTP_FIELD_VERSION(ntpmsg.field),
                  NTP_FIELD_MODE(ntpmsg.field),
                  ntpmsg.stratum,
                  exp2(ntpmsg.precision), ntpmsg.precision,
                  ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a",
                  origin - OFFSET_1900_1970,
                  receive - OFFSET_1900_1970,
                  trans - OFFSET_1900_1970,
                  dest - OFFSET_1900_1970,
                  offset, delay,
                  m->packet_count,
                  m->samples_jitter, spike ? " spike" : "",
                  m->poll_interval_usec / USEC_PER_SEC);

        if (!spike) {
                m->sync = true;
                r = manager_adjust_clock(m, offset, leap_sec);
                if (r < 0)
                        log_error("Failed to call clock_adjtime(): %m");
        }

        log_info("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
                 m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
                 spike ? " (ignored)" : "");

        r = manager_arm_timer(m, m->poll_interval_usec);
        if (r < 0) {
                log_error("Failed to rearm timer: %s", strerror(-r));
                return r;
        }

        return 0;
}

static int manager_listen_setup(Manager *m) {
        union sockaddr_union addr = {};
        static const int tos = IPTOS_LOWDELAY;
        static const int on = 1;
        int r;

        assert(m);

        assert(m->server_socket < 0);
        assert(!m->event_receive);
        assert(m->current_server_address);

        addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family;

        m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
        if (m->server_socket < 0)
                return -errno;

        r = bind(m->server_socket, &addr.sa, m->current_server_address->socklen);
        if (r < 0)
                return -errno;

        r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on));
        if (r < 0)
                return -errno;

        setsockopt(m->server_socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));

        return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m);
}

static int manager_begin(Manager *m) {
        _cleanup_free_ char *pretty = NULL;
        int r;

        assert(m);
        assert_return(m->current_server_name, -EHOSTUNREACH);
        assert_return(m->current_server_address, -EHOSTUNREACH);

        m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;

        server_address_pretty(m->current_server_address, &pretty);
        log_info("Using NTP server %s (%s).", strna(pretty), m->current_server_name->string);
        sd_notifyf(false, "STATUS=Using Time Server %s (%s).", strna(pretty), m->current_server_name->string);

        r = manager_listen_setup(m);
        if (r < 0) {
                log_warning("Failed to setup connection socket: %s", strerror(-r));
                return r;
        }

        r = manager_clock_watch_setup(m);
        if (r < 0)
                return r;

        return manager_send_request(m);
}

void manager_set_server_name(Manager *m, ServerName *n) {
        assert(m);

        if (m->current_server_name == n)
                return;

        m->current_server_name = n;
        m->current_server_address = NULL;

        manager_disconnect(m);

        if (n)
                log_debug("Selected server %s.", n->string);
}