示例#1
0
文件: type.c 项目: ZDOROVAK/libnih
/**
 * type_var_to_string:
 * @parent: parent object for new string,
 * @var: variable to convert.
 *
 * Returns a string for the given variable @var, consisting of the type
 * and variable name separated by a space if appropriate.
 *
 * If @parent is not NULL, it should be a pointer to another object which
 * will be used as a parent for the returned string.  When all parents
 * of the returned string are freed, the returned string will also be
 * freed.
 *
 * Returns: the newly allocated string or NULL if insufficient memory.
 **/
char *
type_var_to_string (const void *parent,
		    TypeVar *   var)
{
	char *str;

	nih_assert (var != NULL);

	if (strchr (var->type, '*')) {
		str = nih_sprintf (parent, "%s%s", var->type, var->name);
	} else {
		str = nih_sprintf (parent, "%s %s", var->type, var->name);
	}

	if (! str)
		return NULL;

	if (var->array) {
		if (! nih_strcat (&str, parent, "[]")) {
			nih_free (str);
			return NULL;
		}
	}

	return str;
}
示例#2
0
void
test_sprintf (void)
{
    char *str1, *str2;

    TEST_FUNCTION ("nih_sprintf");

    /* Check that we can create a formatted string with no parent,
     * it should be allocated with nih_alloc and be the right length.
     */
    TEST_FEATURE ("with no parent");
    TEST_ALLOC_FAIL {
        str1 = nih_sprintf (NULL, "this %s a test %d", "is", 54321);

        if (test_alloc_failed) {
            TEST_EQ_P (str1, NULL);
            continue;
        }

        TEST_ALLOC_PARENT (str1, NULL);
        TEST_ALLOC_SIZE (str1, strlen (str1) + 1);
        TEST_EQ_STR (str1, "this is a test 54321");

        nih_free (str1);
    }


    /* Check that we can create a string with a parent. */
    TEST_FEATURE ("with a parent");
    str1 = nih_sprintf (NULL, "this %s a test %d", "is", 54321);

    TEST_ALLOC_FAIL {
        str2 = nih_sprintf (str1, "another %d test %s",
        12345, "string");

        if (test_alloc_failed) {
            TEST_EQ_P (str2, NULL);
            continue;
        }

        TEST_ALLOC_PARENT (str2, str1);
        TEST_ALLOC_SIZE (str2, strlen (str2) + 1);
        TEST_EQ_STR (str2, "another 12345 test string");

        nih_free (str2);
    }

    nih_free (str1);
}
示例#3
0
/**
 * apparmor_switch:
 * @profile: AppArmor profile to switch to
 *
 * This function switches to a new AppArmor profile on exec
 *
 * Returns: zero on success, -1 on error
 **/
int
apparmor_switch (char *profile)
{
	nih_local char *filename = NULL;
	FILE           *f;

	nih_assert (profile != NULL);

	/* Silently fail if AppArmor isn't enabled. */
	if (! apparmor_available())
		return 0;

	filename = nih_sprintf (NULL, "/proc/%d/attr/exec", getpid());

	if (! filename)
		return -1;

	f = fopen (filename, "w");

	if (! f)
		return -1;

	fprintf (f, "exec %s\n", profile);

	if (fclose (f))
		return -1;

	return 0;
}
示例#4
0
int chown_main(const char *controller, const char *cgroup, struct ucred p,
		struct ucred r, struct ucred v)
{
	char rcgpath[MAXPATHLEN];
	nih_local char *path = NULL;
	uid_t uid;

	/* If caller is not root in his userns, then he can't chown, as
	 * that requires privilege over two uids */
	if (r.uid) {
		if (!hostuid_to_ns(r.uid, r.pid, &uid) || uid != 0) {
			nih_error("%s: Chown requested by non-root uid %u", __func__, r.uid);
			return -1;
		}
	}

	if (!sane_cgroup(cgroup)) {
		nih_error("%s: unsafe cgroup", __func__);
		return -1;
	}

	// Get r's current cgroup in rcgpath
	if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) {
		nih_error("%s: Could not determine the requested cgroup", __func__);
		return -1;
	}
	/* rcgpath + / + cgroup + \0 */
	if (strlen(rcgpath) + strlen(cgroup) > MAXPATHLEN+2) {
		nih_error("%s: Path name too long", __func__);
		return -1;
	}
	path = NIH_MUST( nih_sprintf(NULL, "%s/%s", rcgpath, cgroup) );
	if (realpath_escapes(path, rcgpath)) {
		nih_error("%s: Invalid path %s", __func__, path);
		return -1;
	}
	// is r allowed to descend under the parent dir?
	if (!may_access(r.pid, r.uid, r.gid, path, O_RDONLY)) {
		nih_error("%s: pid %d (uid %u gid %u) may not read under %s", __func__,
			r.pid, r.uid, r.gid, path);
		return -1;
	}

	// does r have privilege over the cgroup dir?
	if (!may_access(r.pid, r.uid, r.gid, path, O_RDWR)) {
		nih_error("%s: Pid %d may not chown %s\n", __func__, r.pid, path);
		return -1;
	}

	// go ahead and chown it.
	if (!chown_cgroup_path(path, v.uid, v.gid, false)) {
		nih_error("%s: Failed to change ownership on %s to %u:%u", __func__,
			path, v.uid, v.gid);
		return -1;
	}

	return 0;
}
示例#5
0
文件: pam_cgm.c 项目: hallyn/pam-cgm
static void prune_user_cgs(const char *user)
{
	nih_local char **list = NULL;
	nih_local char *path = NULL;
	int i;

	path = NIH_MUST( nih_sprintf(NULL, "user/%s", user) );
	list = cgm_list_children(path);
	if (!list)
		return;
	for (i = 0; list[i]; i++) {
		nih_local char *cgpath = NIH_MUST( nih_sprintf(NULL, "%s/%s", path, list[i]) );
		if (!cgm_cg_has_tasks(cgpath))
			cgm_clear_cgroup(cgpath);
	}
	if (!cgm_cg_has_tasks(path))
		cgm_clear_cgroup(path);
}
示例#6
0
int chmod_main(const char *controller, const char *cgroup, const char *file,
		struct ucred p, struct ucred r, int mode)
{
	char rcgpath[MAXPATHLEN];
	nih_local char *path = NULL;

	if (!sane_cgroup(cgroup)) {
		nih_error("%s: unsafe cgroup", __func__);
		return -1;
	}

	if (file && ( strchr(file, '/') || strchr(file, '\\')) ) {
		nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
				"invalid file");
		return -1;
	}

	// Get r's current cgroup in rcgpath
	if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) {
		nih_error("%s: Could not determine the requested cgroup", __func__);
		return -1;
	}

	path = NIH_MUST( nih_sprintf(NULL, "%s/%s", rcgpath, cgroup) );
	if (file && strlen(file))
		NIH_MUST( nih_strcat_sprintf(&path, NULL, "/%s", file) );
	if (realpath_escapes(path, rcgpath)) {
		nih_error("%s: Invalid path %s", __func__, path);
		return -1;
	}
	// is r allowed to descend under the parent dir?
	if (!may_access(r.pid, r.uid, r.gid, path, O_RDONLY)) {
		nih_error("%s: pid %d (uid %u gid %u) may not read under %s", __func__,
			r.pid, r.uid, r.gid, path);
		return -1;
	}

	// does r have privilege over the cgroup dir?
	if (!may_access(r.pid, r.uid, r.gid, path, O_RDWR)) {
		nih_error("%s: Pid %d may not chmod %s\n", __func__, r.pid, path);
		return -1;
	}

	// go ahead and chmod it.
	if (!chmod_cgroup_path(path, mode)) {
		nih_error("%s: Failed to change mode on %s to %d", __func__,
			path, mode);
		return -1;
	}

	return 0;
}
示例#7
0
/**
 * shutdown_now:
 *
 * Send a signal to init to shut down the machine.
 *
 * This does not return.
 **/
static void
shutdown_now (void)
{
	nih_local char **extra_env = NULL;
	NihDBusError *   dbus_err;

	if (init_halt) {
		char *e;

		e = NIH_MUST (nih_sprintf (NULL, "INIT_HALT=%s", init_halt));

		extra_env = NIH_MUST (nih_str_array_new (NULL));
		NIH_MUST (nih_str_array_addp (&extra_env, NULL, NULL, e));
	}

	if (sysv_change_runlevel (runlevel, extra_env, NULL, NULL) < 0) {
		dbus_err = (NihDBusError *)nih_error_get ();

		if ((dbus_err->number != NIH_DBUS_ERROR)
		    || strcmp (dbus_err->name, DBUS_ERROR_NO_SERVER)) {
			nih_fatal ("%s", dbus_err->message);
			nih_free (dbus_err);
			exit (1);
		}

		nih_free (dbus_err);

		/* Connection Refused means that init isn't running, this
		 * might mean we've just upgraded to upstart and haven't
		 * yet rebooted ... so try /dev/initctl
		 */
		sysvinit_shutdown ();
	}

	unlink (ETC_NOLOGIN);
	nih_main_unlink_pidfile ();

	exit (0);
}
示例#8
0
/*
 * Given a directory path, chown it to a userid.
 * We will chown $path and try to chown $path/tasks and $path/procs.
 * if @all_children is true, then chown all files under @path.  (This
 * is for the case where the caller had the rights to mkdir the path.
 * In that case he gets to write to all files - the kernel will ensure
 * hierarhical limits)
 *
 * Return true so long as we could chown the directory itself.
 */
bool chown_cgroup_path(const char *path, uid_t uid, gid_t gid, bool all_children)
{
	int len = strlen(path), ret;
	nih_local char *fpath = NULL;

	if (chown(path, uid, gid) < 0)
		return false;
	if (all_children) {
		struct dirent dirent, *direntp;
		char fpath[MAXPATHLEN];
		DIR *d = opendir(path);
		if (len >= MAXPATHLEN)
			return true;
		strcpy(fpath, path);
		while (readdir_r(d, &dirent, &direntp) == 0 && direntp) {
			if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, ".."))
				continue;
			ret = snprintf(fpath+len, MAXPATHLEN-len, "/%s", direntp->d_name);
			if (ret < 0 || ret >= MAXPATHLEN-len)
				continue;
			if (chown(fpath, uid, gid) < 0)
				nih_info("Failed to chown file %s to %d:%d",
					fpath, (int)uid, (int)gid);
		}
		closedir(d);
	} else
		fpath = nih_sprintf(NULL, "%s/cgroup.procs", path);
		if (!fpath)
			return true;
		if (chown(fpath, uid, gid) < 0)
			nih_info("Failed to chown procs file %s", fpath);
		sprintf(fpath+len, "/tasks");
		if (chown(fpath, uid, gid) < 0)
			nih_info("Failed to chown tasks file %s", fpath);
	return true;
}
示例#9
0
void
test_libupstart (void)
{
	nih_local NihDBusProxy  *upstart = NULL;
	nih_local char          *version = NULL;
	int                      ret;
	pid_t                    upstart_pid;
	pid_t                    dbus_pid;
	char                     xdg_runtime_dir[PATH_MAX];
	nih_local char          *orig_xdg_runtime_dir = NULL;
	nih_local char          *session_file = NULL;
	nih_local char          *path = NULL;

	TEST_GROUP ("libupstart");

	TEST_FEATURE ("version");

        TEST_FILENAME (xdg_runtime_dir);
        TEST_EQ (mkdir (xdg_runtime_dir, 0755), 0);

	/* Take care to avoid disrupting users environment by saving and
	 * restoring this variable (assuming the tests all pass...).
	 */
	orig_xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR");
	if (orig_xdg_runtime_dir)
		orig_xdg_runtime_dir = NIH_MUST (nih_strdup (NULL, orig_xdg_runtime_dir));

	assert0 (setenv ("XDG_RUNTIME_DIR", xdg_runtime_dir, 1));

	/*******************************************************************/

	/* Create a private Session Init instance to connect to */
	TEST_DBUS (dbus_pid);
	START_UPSTART (upstart_pid, TRUE);

	upstart = upstart_open (NULL);
	TEST_NE_P (upstart, NULL);

	/* Basic test (that does not change the state of the system
	 * running this test) to see if we can query version of running
	 * Upstart instance.
	 */
	ret = upstart_get_version_sync (NULL, upstart, &version);
	TEST_EQ (ret, 0);

	nih_message ("Running instance version: '%s'", version);
	assert0 (fnmatch ("init (upstart*)", version, 0x0));

	STOP_UPSTART (upstart_pid);
	TEST_DBUS_END (dbus_pid);

	/*******************************************************************/

	if (orig_xdg_runtime_dir) {
		/* restore */
		setenv ("XDG_RUNTIME_DIR", orig_xdg_runtime_dir, 1);
	} else {
		assert0 (unsetenv ("XDG_RUNTIME_DIR"));
	}

	session_file = get_session_file (xdg_runtime_dir, upstart_pid);
	unlink (session_file);

	/* Remove the directory tree the Session Init created */
	path = NIH_MUST (nih_sprintf (NULL, "%s/upstart/sessions", xdg_runtime_dir));
        assert0 (rmdir (path));
	path = NIH_MUST (nih_sprintf (NULL, "%s/upstart", xdg_runtime_dir));
        assert0 (rmdir (path));

        assert0 (rmdir (xdg_runtime_dir));
}
示例#10
0
void
test_cgroup_job_start (void)
{
	char             confdir[PATH_MAX];
	char             logdir[PATH_MAX];
	char             flagfile[PATH_MAX];
	nih_local char  *cmd = NULL;
	pid_t            dbus_pid = 0;
	pid_t            upstart_pid = 0;
	char           **output;
	size_t           lines;
	size_t           len;
	nih_local char  *logfile = NULL;
	nih_local char  *logfile_name = NULL;
	nih_local char  *contents = NULL;

	if (geteuid ()) {
		printf ("INFO: skipping %s tests as not running as root\n", __func__);
		fflush (NULL);
		return;
	}

	TEST_GROUP ("cgroup manager handling");

        TEST_FILENAME (confdir);
        TEST_EQ (mkdir (confdir, 0755), 0);

        TEST_FILENAME (logdir);
        TEST_EQ (mkdir (logdir, 0755), 0);

        TEST_FILENAME (flagfile);

	/* Use the "secret" interface */
	TEST_EQ (setenv ("UPSTART_CONFDIR", confdir, 1), 0);
	TEST_EQ (setenv ("UPSTART_LOGDIR", logdir, 1), 0);

	TEST_DBUS (dbus_pid);

	/*******************************************************************/
	TEST_FEATURE ("Ensure startup job does not start until cgmanager available");

	contents = nih_sprintf (NULL, 
			"start on startup\n"
			"\n"
			"cgroup memory mem-%s\n"
			"\n"
			"exec echo hello\n",
			__func__);
	TEST_NE_P (contents, NULL);

	CREATE_FILE (confdir, "cgroup.conf", contents);

	logfile_name = NIH_MUST (nih_sprintf (NULL, "%s/%s",
				logdir,
				"cgroup.log"));

	start_upstart_common (&upstart_pid, FALSE, FALSE, confdir, logdir, NULL);

	cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "cgroup");
	TEST_NE_P (cmd, NULL);
	RUN_COMMAND (NULL, cmd, &output, &lines);
	TEST_EQ (lines, 1);

	/* job should *NOT* start on startup */
	TEST_EQ_STR (output[0], "cgroup stop/waiting");
	nih_free (output);

	TEST_FALSE (file_exists (logfile_name));

	cmd = nih_sprintf (NULL, "%s notify-cgroup-manager-address %s 2>&1",
			get_initctl (),
			CGMANAGER_DBUS_SOCK);
	TEST_NE_P (cmd, NULL);
	RUN_COMMAND (NULL, cmd, &output, &lines);
	TEST_EQ (lines, 0);

	WAIT_FOR_FILE (logfile_name);

	logfile = nih_file_read (NULL, logfile_name, &len);
	TEST_NE_P (logfile, NULL);

	TEST_EQ_STR (logfile, "hello\r\n");

	DELETE_FILE (confdir, "cgroup.conf");
	assert0 (unlink (logfile_name));

	/*******************************************************************/
	TEST_FEATURE ("Ensure bogus cgroups don't crash init");

	contents = nih_sprintf (NULL, 
			"cgroup name\n"
			"\n"
			"exec echo hello\n");
	TEST_NE_P (contents, NULL);

	CREATE_FILE (confdir, "cgroup-name.conf", contents);

	logfile_name = NIH_MUST (nih_sprintf (NULL, "%s/%s",
				logdir,
				"cgroup-name.log"));

	cmd = nih_sprintf (NULL, "%s status %s 2>&1", get_initctl (), "cgroup-name");
	TEST_NE_P (cmd, NULL);
	RUN_COMMAND (NULL, cmd, &output, &lines);
	TEST_EQ (lines, 1);

	/* job is not running yet */
	TEST_EQ_STR (output[0], "cgroup-name stop/waiting");
	nih_free (output);

	TEST_FALSE (file_exists (logfile_name));

	cmd = nih_sprintf (NULL, "%s start %s 2>&1", get_initctl (), "cgroup-name");
	TEST_NE_P (cmd, NULL);
	RUN_COMMAND (NULL, cmd, &output, &lines);
	TEST_EQ (lines, 1);

        TEST_EQ_STR (output[0], "initctl: Job failed to start");

	DELETE_FILE (confdir, "cgroup-name.conf");
	/*******************************************************************/

	STOP_UPSTART (upstart_pid);
	TEST_DBUS_END (dbus_pid);

        TEST_EQ (rmdir (confdir), 0);
        TEST_EQ (rmdir (logdir), 0);

	/*******************************************************************/

}
示例#11
0
/**
 * session_from_dbus:
 * @parent: parent,
 * @message: D-Bus message.
 *
 * Create a new session, based on the specified D-Bus message.
 *
 * Return new Session, or NULL on error.
 **/
Session *
session_from_dbus (const void     *parent,
		   NihDBusMessage *message)
{
	const char     *sender;
	DBusError       dbus_error;
	unsigned long   unix_user;
	unsigned long   unix_process_id;
	char            root[PATH_MAX];
	Session        *session;
	struct passwd  *pwd;
	nih_local char *conf_path = NULL;

	nih_assert (message != NULL);

	/* Handle explicit command-line request and alternative request
	 * method (primarily for test framework) to disable session support.
	 */
	if (disable_sessions || getenv ("UPSTART_NO_SESSIONS"))
		return NULL;

	session_init ();

	/* Ask D-Bus nicely for the origin uid and/or pid of the caller;
	 * sadly we can't ask the bus daemon for the origin pid, so that
	 * one will just have to stay user-session only.
	 */
	dbus_error_init (&dbus_error);

	sender = dbus_message_get_sender (message->message);
	if (sender) {
		unix_user = dbus_bus_get_unix_user (message->connection, sender,
						    &dbus_error);
		if (unix_user == (unsigned long)-1) {
			dbus_error_free (&dbus_error);
			unix_user = 0;
		}

		unix_process_id = 0;

	} else {
		if (! dbus_connection_get_unix_user (message->connection,
						     &unix_user))
			unix_process_id = 0;

		if (! dbus_connection_get_unix_process_id (message->connection,
							   &unix_process_id))
			unix_process_id = 0;
	}

	/* If we retrieved a process id, look up the root path for it;
	 * if it's just '/' don't worry so much about it.
	 */
	if (unix_process_id) {
		nih_local char *symlink = NULL;
		ssize_t len;

		symlink = NIH_MUST (nih_sprintf (NULL, "/proc/%lu/root",
						 unix_process_id));
		len = readlink (symlink, root, sizeof root);
		if (len < 0)
			return NULL;

		root[len] = '\0';

		if (! strcmp (root, "/")) {
			unix_process_id = 0;
			if (! unix_user)
				return NULL;
		}

	} else if (! unix_user) {
		/* No process id or user id found, return the NULL session */
		return NULL;
	}

	if (unix_user) {
		pwd = getpwuid (unix_user);

		if (! pwd || ! pwd->pw_dir) {
			nih_error ("%lu: %s: %s", unix_user,
				   _("Unable to lookup home directory"),
				   strerror (errno));
			return NULL;
		}

		NIH_MUST (nih_strcat_sprintf (&conf_path, NULL, "%s/%s",
					pwd->pw_dir, USERCONFDIR));
	}


	/* Now find in the existing Sessions list */
	NIH_LIST_FOREACH_SAFE (sessions, iter) {
		Session *session = (Session *)iter;

		if (unix_process_id) {
			if (! session->chroot)
				continue;

			/* ignore sessions relating to other chroots */
			if (strcmp (session->chroot, root))
				continue;
		}

		/* ignore sessions relating to other users */
		if (unix_user != session->user)
			continue;

		/* Found a user with the same uid but different
		 * conf_dir to the existing session user. Either the
		 * original user has been deleted and a new user created
		 * with the same uid, or the original users home
		 * directory has changed since they first started
		 * running jobs. Whatever the reason, we (can only) honour
		 * the new value.
		 *
		 * Since multiple users with the same uid are considered
		 * to be "the same user", invalidate the old path,
		 * allowing the correct new path to be set below.
		 *
		 * Note that there may be a possibility of trouble if
		 * the scenario relates to a deleted user and that original
		 * user still has jobs running. However, if that were the
		 * case, those jobs would likely fail anyway since they
		 * would have no working directory due to the original
		 * users home directory being deleted/changed/made inaccessible.
		 */
		if (unix_user && conf_path && session->conf_path &&
				strcmp (conf_path, session->conf_path)) {
			nih_free (session->conf_path);
			session->conf_path = NULL;
		}

		if (! session->conf_path)
			session_create_conf_source (session);

		return session;
	}
示例#12
0
/**
 * wall:
 * @message: message to send.
 *
 * Send a message to all logged in users; based largely on the code from
 * bsdutils.  This is done in a child process to stop anything blocking.
 **/
static void
wall (const char *message)
{
	struct sigaction act;
	struct utmpx *   ent;
	pid_t            pid;
	time_t           now;
	struct tm *      tm;
	char *           user;
	char *           tty;
	char             hostname[MAXHOSTNAMELEN];
	char *           banner1;
	char *           banner2;

	pid = fork ();
	if (pid < 0) {
		nih_warn (_("Unable to fork child-process to warn users: %s"),
			  strerror (errno));
		return;
	} else if (pid > 0) {
		return;
	}

	/* Break syscalls with SIGALRM */
	act.sa_handler = alarm_handler;
	act.sa_flags = 0;
	sigemptyset (&act.sa_mask);
	sigaction (SIGALRM, &act, NULL);


	/* Get username for banner */
	user = getlogin ();
	if (! user) {
		struct passwd *pw;

		pw = getpwuid (getuid ());
		if (pw)
			user = pw->pw_name;
	}
	if (! user) {
		if (getuid ()) {
			user = NIH_MUST (nih_sprintf (NULL, "uid %d",
						      getuid ()));
		} else {
			user = "******";
		}
	}

	/* Get hostname for banner */
	gethostname (hostname, sizeof (hostname));

	/* Get terminal for banner */
	tty = ttyname (0);
	if (! tty)
		tty = "unknown";

	/* Get time */
	now = time (NULL);
	tm = localtime (&now);

	/* Construct banner */
	banner1 = nih_sprintf (NULL, _("Broadcast message from %s@%s"),
			       user, hostname);
	banner2 = nih_sprintf (NULL, _("(%s) at %d:%02d ..."),
			       tty, tm->tm_hour, tm->tm_min);


	/* Iterate entries in the utmp file */
	setutxent ();
	while ((ent = getutxent ()) != NULL) {
		char dev[PATH_MAX + 1];
		int  fd;

		/* Ignore entries without a name, or not a user process */
		if ((ent->ut_type != USER_PROCESS)
		    || (! strlen (ent->ut_user)))
			continue;

		/* Construct the device path */
		if (strncmp (ent->ut_line, DEV "/", 5)) {
			snprintf (dev, sizeof (dev),
				  "%s/%s", DEV, ent->ut_line);
		} else {
			snprintf (dev, sizeof (dev), "%s", ent->ut_line);
		}

		alarm (2);
		fd = open (dev, O_WRONLY | O_NDELAY | O_NOCTTY);
		if ((fd >= 0) && isatty (fd)) {
			FILE *term;

			term = fdopen (fd, "w");
			if (term) {
				fprintf (term, "\007\r\n%s\r\n\t%s\r\n\r\n",
					 banner1, banner2);
				fputs (message, term);
				fflush (term);
				fclose (term);
			}
		}
		alarm (0);
	}
	endutxent ();

	nih_free (banner1);
	nih_free (banner2);

	exit (0);
}
示例#13
0
/**
 * warning_message:
 * @message: user message.
 *
 * Prefixes the message with details about how long until the shutdown
 * completes.
 *
 * Returns: newly allocated string.
 **/
static char *
warning_message (const char *message)
{
	nih_local char *banner = NULL;
	char *          msg;

	nih_assert (message != NULL);

	if ((runlevel == '0')
	    && init_halt && (! strcmp (init_halt, "POWEROFF"))) {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "power off in %d minute!",
					 "The system is going down for "
					 "power off in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"power off NOW!"));
		}
	} else if (runlevel == '0') {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "halt in %d minute!",
					 "The system is going down for "
					 "halt in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"halt NOW!"));
		}
	} else if (runlevel == '1') {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "maintenance in %d minute!",
					 "The system is going down for "
					 "maintenance in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"maintenance NOW!"));
		}
	} else if (runlevel == '6') {
		if (delay) {
			banner = nih_sprintf (
				NULL, _n("The system is going down for "
					 "reboot in %d minute!",
					 "The system is going down for "
					 "reboot in %d minutes!",
					 delay), delay);
		} else {
			banner = nih_strdup (
				NULL, _("The system is going down for "
					"reboot NOW!"));
		}
	}

	if (! banner)
		return NULL;

	msg = nih_sprintf (NULL, "\r%s\r\n%s", banner, message);

	return msg;
}
示例#14
0
static void
udev_monitor_watcher (struct udev_monitor *udev_monitor,
		      NihIoWatch *         watch,
		      NihIoEvents          events)
{
	struct udev_device *    udev_device;
	nih_local char *        subsystem = NULL;
	nih_local char *        action = NULL;
	nih_local char *        kernel = NULL;
	nih_local char *        devpath = NULL;
	nih_local char *        devname = NULL;
	nih_local char *        name = NULL;
	nih_local char **       env = NULL;
	const char *            value = NULL;
	size_t                  env_len = 0;
	DBusPendingCall *       pending_call;
	char                 *(*copy_string)(const void *, const char *) = NULL;


	udev_device = udev_monitor_receive_device (udev_monitor);
	if (! udev_device)
		return;

	copy_string = no_strip_udev_data ? nih_strdup : make_safe_string;

	value = udev_device_get_subsystem (udev_device);
	subsystem = value ? copy_string (NULL, value) : NULL;

	value = udev_device_get_action (udev_device);
	action = value ? copy_string (NULL, value) : NULL;

	value = udev_device_get_sysname (udev_device);
	kernel = value ? copy_string (NULL, value) : NULL;

	value = udev_device_get_devpath (udev_device);
	devpath = value ? copy_string (NULL, value) : NULL;

	value = udev_device_get_devnode (udev_device);
	devname = value ? copy_string (NULL, value) : NULL;

	/* Protect against the "impossible" */
	if (! action)
		goto out;

	if (! strcmp (action, "add")) {
		name = NIH_MUST (nih_sprintf (NULL, "%s-device-added",
					      subsystem));
	} else if (! strcmp (action, "change")) {
		name = NIH_MUST (nih_sprintf (NULL, "%s-device-changed",
					      subsystem));
	} else if (! strcmp (action, "remove")) {
		name = NIH_MUST (nih_sprintf (NULL, "%s-device-removed",
					      subsystem));
	} else {
		name = NIH_MUST (nih_sprintf (NULL, "%s-device-%s",
					      subsystem, action));
	}

	env = NIH_MUST (nih_str_array_new (NULL));

	if (kernel) {
		nih_local char *var = NULL;

		var = NIH_MUST (nih_sprintf (NULL, "KERNEL=%s", kernel));
		NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
	}

	if (devpath) {
		nih_local char *var = NULL;

		var = NIH_MUST (nih_sprintf (NULL, "DEVPATH=%s", devpath));
		NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
	}

	if (devname) {
		nih_local char *var = NULL;

		var = NIH_MUST (nih_sprintf (NULL, "DEVNAME=%s", devname));
		NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
	}

	if (subsystem) {
		nih_local char *var = NULL;

		var = NIH_MUST (nih_sprintf (NULL, "SUBSYSTEM=%s", subsystem));
		NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
	}

	if (action) {
		nih_local char *var = NULL;

		var = NIH_MUST (nih_sprintf (NULL, "ACTION=%s", action));
		NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
	}

	for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device);
	     list_entry != NULL;
	     list_entry = udev_list_entry_get_next (list_entry)) {
		nih_local char *udev_name = NULL;
		nih_local char *udev_value = NULL;
		nih_local char *var = NULL;

		udev_name = copy_string (NULL, udev_list_entry_get_name (list_entry));

		if (! strcmp (udev_name, "DEVPATH"))
			continue;
		if (! strcmp (udev_name, "DEVNAME"))
			continue;
		if (! strcmp (udev_name, "SUBSYSTEM"))
			continue;
		if (! strcmp (udev_name, "ACTION"))
			continue;

		udev_value = copy_string (NULL, udev_list_entry_get_value (list_entry));

		var = NIH_MUST (nih_sprintf (NULL, "%s=%s", udev_name, udev_value));
		NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
	}

	nih_debug ("%s %s", name, devname ? devname : "");

	pending_call = upstart_emit_event (upstart,
			name, env, FALSE,
			NULL, emit_event_error, NULL,
			NIH_DBUS_TIMEOUT_NEVER);

	if (! pending_call) {
		NihError *err;
		int saved = errno;

		err = nih_error_get ();
		nih_warn ("%s", err->message);

		if (saved != ENOMEM && subsystem)
			nih_warn ("Likely that udev '%s' event contains binary garbage", subsystem);

		nih_free (err);
	}

	dbus_pending_call_unref (pending_call);

out:
	udev_device_unref (udev_device);
}