Example #1
0
static int on_runlevel(Context *c) {
        int r = 0, q, previous, runlevel;

        assert(c);

        /* We finished changing runlevel, so let's write the
         * utmp record and send the audit msg */

        /* First, get last runlevel */
        q = utmp_get_runlevel(&previous, NULL);

        if (q < 0) {
                if (q != -ESRCH && q != -ENOENT) {
                        log_error("Failed to get current runlevel: %s", strerror(-q));
                        return q;
                }

                previous = 0;
        }

        /* Secondly, get new runlevel */
        runlevel = get_current_runlevel(c);

        if (runlevel < 0)
                return runlevel;

        if (previous == runlevel)
                return 0;

#ifdef HAVE_AUDIT
        if (c->audit_fd >= 0) {
                _cleanup_free_ char *s = NULL;

                if (asprintf(&s, "old-level=%c new-level=%c",
                             previous > 0 ? previous : 'N',
                             runlevel > 0 ? runlevel : 'N') < 0)
                        return log_oom();

                if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, NULL, NULL, NULL, 1) < 0 &&
                    errno != EPERM) {
                        log_error("Failed to send audit message: %m");
                        r = -errno;
                }
        }
#endif

        q = utmp_put_runlevel(runlevel, previous);
        if (q < 0 && q != -ESRCH && q != -ENOENT) {
                log_error("Failed to write utmp record: %s", strerror(-q));
                r = q;
        }

        return r;
}
Example #2
0
static int on_runlevel(Context *c) {
        int r = 0, q, previous, runlevel;

        assert(c);

        /* We finished changing runlevel, so let's write the
         * utmp record and send the audit msg */

        /* First, get last runlevel */
        if ((q = utmp_get_runlevel(&previous, NULL)) < 0) {

                if (q != -ESRCH && q != -ENOENT) {
                        log_error("Failed to get current runlevel: %s", strerror(-q));
                        return q;
                }

                /* Hmm, we didn't find any runlevel, that means we
                 * have been rebooted */
                r = on_reboot(c);
                previous = 0;
        }

        /* Secondly, get new runlevel */
        if ((runlevel = get_current_runlevel(c)) < 0)
                return runlevel;

        if (previous == runlevel)
                return 0;

#ifdef HAVE_AUDIT
        if (c->audit_fd >= 0) {
                char *s = NULL;

                if (asprintf(&s, "old-level=%c new-level=%c",
                             previous > 0 ? previous : 'N',
                             runlevel > 0 ? runlevel : 'N') < 0)
                        return -ENOMEM;

                if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, NULL, NULL, NULL, 1) < 0) {
                        log_error("Failed to send audit message: %m");
                        r = -errno;
                }

                free(s);
        }
#endif

        if ((q = utmp_put_runlevel(0, runlevel, previous)) < 0) {
                log_error("Failed to write utmp record: %s", strerror(-q));
                r = q;
        }

        return r;
}
Example #3
0
static int utmp_handler(int fd, void *data, struct lxc_epoll_descr *descr)
{
	struct inotify_event *ie;
	int size, ret, length;

	struct lxc_utmp *utmp_data = (struct lxc_utmp *)data;

	/*
	 * we're monitoring a directory. ie->name is not included in
	 * sizeof(struct inotify_event) if we don't read it all at once,
	 * read gives us EINVAL, so we read and cast to struct ie
	 */
	char buffer[MAXPATHLEN];

	if (ioctl(fd, FIONREAD, &size) < 0) {
		SYSERROR("cannot determine the size of this notification");
		return -1;
	}

	if (read(fd, buffer, size) < 0) {
		SYSERROR("failed to read notification");
		return -1;
	}

	ie = (struct inotify_event *)buffer;

	if (ie->len <= 0) {

		if (ie->mask & IN_UNMOUNT) {
			DEBUG("watched directory removed");
			goto out;
		}

		SYSERROR("inotify event with no name (mask %d)", ie->mask);
		return -1;
	}

	ret = 0;

	DEBUG("got inotify event %d for %s", ie->mask, ie->name);

	length = (4 < ie->len) ? 4 : ie->len;

	/* only care about utmp */

	if (strncmp(ie->name, "utmp", length))
		return 0;

	if (ie->mask & (IN_MODIFY | IN_CREATE))
		ret = utmp_get_runlevel(utmp_data);

	if (ret < 0)
		goto out;

	/* container halting, from running or starting state */
	if (utmp_data->curr_runlevel == '0'
	    && ((utmp_data->container_state == CONTAINER_RUNNING)
		|| (utmp_data->container_state == CONTAINER_STARTING))) {
		utmp_data->container_state = CONTAINER_HALTING;
		if (utmp_data->timer_fd == -1)
			lxc_utmp_add_timer(descr, utmp_shutdown_handler, data);
		DEBUG("Container halting");
		goto out;
	}

	/* container rebooting, from running or starting state */
	if (utmp_data->curr_runlevel == '6'
	    && ((utmp_data->container_state == CONTAINER_RUNNING)
		|| (utmp_data->container_state == CONTAINER_STARTING))) {
		utmp_data->container_state = CONTAINER_REBOOTING;
		if (utmp_data->timer_fd == -1)
			lxc_utmp_add_timer(descr, utmp_shutdown_handler, data);
		DEBUG("Container rebooting");
		goto out;
	}

	/* normal operation, running, from starting state. */
	if (utmp_data->curr_runlevel > '0' && utmp_data->curr_runlevel < '6') {
		utmp_data->container_state = CONTAINER_RUNNING;
		if (utmp_data->timer_fd > 0)
			lxc_utmp_del_timer(descr, utmp_data);
		DEBUG("Container running");
		goto out;
	}

out:
	return 0;
}