Beispiel #1
0
char *file_read_string(void *parent, const char *path)
{
	int ret, fd = open(path, O_RDONLY);
	char *string = NULL;
	off_t sz = 0;
	if (fd < 0) {
		nih_error("Error opening %s: %s", path, strerror(errno));
		return NULL;
	}

	while (1) {
		char *n;
		sz += 1024;
		if (!(n = nih_realloc(string, parent, sz))) {
			nih_free(string);
			string = NULL;
			goto out;
		}
		string = n;
		memset(string+sz-1024, 0, 1024);
		ret = read(fd, string+sz-1024, 1024);
		if (ret < 0) {
			nih_free(string);
			string = NULL;
			goto out;
		}
		if (ret < 1024)
			break;
	}
out:
	close(fd);
	drop_newlines(string);
	return string;
}
Beispiel #2
0
/**
 * fgets_alloc:
 * @stream: stdio stream to read from.
 *
 * Reads from stream up to EOF or a newline, without any line-length
 * limitations.
 *
 * Returns: static string containing the entire line WITHOUT the
 * terminating newline, or NULL if end of file is reached and nothing
 * was read.
 **/
char *
fgets_alloc (const void *parent,
	     FILE *      stream)
{
        char * buf = NULL;
        size_t buf_sz = 0;
	size_t buf_len = 0;

	nih_assert (stream != NULL);

	for (;;) {
		char *ret;
		char *pos;

		if (buf_sz <= (buf_len + 1)) {
			buf_sz += 4096;
			buf = NIH_MUST (nih_realloc (buf, parent, buf_sz));
		}

		ret = fgets (buf + buf_len, buf_sz - buf_len, stream);
		if ((! ret) && (! buf_len)) {
			nih_free (buf);
			return NULL;
		} else if (! ret) {
			return buf;
		}

		buf_len += strlen (ret);
		pos = strchr (ret, '\n');
		if (pos) {
			*pos = '\0';
			break;
		}
	}

	return buf;
}
Beispiel #3
0
void
test_realloc (void)
{
	void *ptr1;
	void *ptr2;
	void *ptr3;

	TEST_FUNCTION ("nih_realloc");

	/* Check that nih_realloc behaves like nih_alloc if the pointer is
	 * NULL (it should, in fact, just call it)
	 */
	TEST_FEATURE ("as nih_alloc");
	ptr1 = nih_realloc (NULL, NULL, 4096);
	memset (ptr1, 'x', 4096);

	TEST_ALLOC_SIZE (ptr1, 4096);
	TEST_ALLOC_PARENT (ptr1, NULL);

	nih_free (ptr1);


	/* Check that nih_realloc works if the block doesn't have a parent.
	 */
	TEST_FEATURE ("with no parent");
	ptr1 = nih_alloc (NULL, 4096);
	memset (ptr1, 'x', 4096);

	ptr1 = nih_realloc (ptr1, NULL, 8096);
	memset (ptr1, 'x', 8096);

	TEST_ALLOC_SIZE (ptr1, 8096);
	TEST_ALLOC_PARENT (ptr1, NULL);


	/* Check that nih_realloc works if the block has a parent, the size
	 * should change but the parent should remain the same.
	 */
	TEST_FEATURE ("with a parent");
	ptr2 = nih_alloc (ptr1, 5);
	memset (ptr2, 'x', 5);

	ptr2 = nih_realloc (ptr2, ptr1, 10);
	memset (ptr2, 'x', 10);

	TEST_ALLOC_SIZE (ptr2, 10);
	TEST_ALLOC_PARENT (ptr2, ptr1);

	nih_free (ptr1);


	/* Check that nih_realloc works if the block being reallocated has
	 * a child.  This is fiddly as they need their parent pointers
	 * adjusted.
	 */
	TEST_FEATURE ("with a child");
	ptr1 = nih_alloc (NULL, 128);
	memset (ptr1, 'x', 128);

	ptr2 = nih_alloc (ptr1, 512);
	memset (ptr2, 'x', 512);

	ptr3 = nih_realloc (ptr1, NULL, 1024);
	memset (ptr3, 'x', 1024);

	TEST_ALLOC_PARENT (ptr2, ptr3);

	nih_free (ptr3);


	/* Check that nih_realloc returns NULL and doesn't alter the block
	 * if the allocator fails.
	 */
	TEST_FEATURE ("with failing realloc");
	ptr1 = nih_alloc (NULL, 10);
	assert (ptr1);
	memset (ptr1, 'x', 10);

	__nih_realloc = realloc_null;
	ptr2 = nih_realloc (ptr1, NULL, 200);
	__nih_realloc = realloc;

	TEST_EQ_P (ptr2, NULL);
	TEST_ALLOC_SIZE (ptr1, 10);

	nih_free (ptr1);
}
Beispiel #4
0
int list_controllers_main (void *parent, char ***output)
{
	DBusMessage *message = NULL, *reply = NULL;
	char **         output_local = NULL;
	DBusError       error;
	DBusMessageIter iter;
	int		ret = -1;
	DBusMessageIter output_local_iter;
	size_t          output_local_size;

	*output = NULL;
	message = dbus_message_new_method_call(dbus_bus_get_unique_name(server_conn),
			"/org/linuxcontainers/cgmanager",
			"org.linuxcontainers.cgmanager0_0", "ListControllers");

	dbus_error_init (&error);

	reply = dbus_connection_send_with_reply_and_block (server_conn, message, -1, &error);
	if (! reply) {
		dbus_message_unref (message);

		nih_error("%s: error completing dbus request: %s %s", __func__,
			error.name, error.message);

		dbus_error_free (&error);
		return -1;
	}
	dbus_message_unref (message);

	dbus_message_iter_init (reply, &iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
		goto out;

	dbus_message_iter_recurse (&iter, &output_local_iter);

	output_local_size = 0;
	output_local = NULL;

	output_local = NIH_MUST( nih_alloc (parent, sizeof (char *)) );

	output_local[output_local_size] = NULL;

	while (dbus_message_iter_get_arg_type (&output_local_iter) != DBUS_TYPE_INVALID) {
		const char *output_local_element_dbus;
		char **     output_local_tmp;
		char *      output_local_element;

		if (dbus_message_iter_get_arg_type (&output_local_iter) != DBUS_TYPE_STRING)
			goto out;

		dbus_message_iter_get_basic (&output_local_iter, &output_local_element_dbus);

		output_local_element = NIH_MUST( nih_strdup (output_local, output_local_element_dbus) );

		dbus_message_iter_next (&output_local_iter);

		output_local_tmp = NIH_MUST( nih_realloc (output_local, parent, sizeof (char *) * (output_local_size + 2)) );

		output_local = output_local_tmp;
		output_local[output_local_size] = output_local_element;
		output_local[output_local_size + 1] = NULL;

		output_local_size++;
	}

	dbus_message_iter_next (&iter);

	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
		goto out;

	*output = output_local;

	ret = 0;

out:
	if (reply)
		dbus_message_unref (reply);
	if (ret)
		nih_free (output_local);
	return ret;
}
Beispiel #5
0
int
main (int   argc,
      char *argv[])
{
	char **         args;
	nih_local char *message = NULL;
	size_t          messagelen;
	nih_local char *msg = NULL;
	int             arg;
	pid_t           pid = 0;

	nih_main_init (argv[0]);

	nih_option_set_usage (_("TIME [MESSAGE]"));
	nih_option_set_synopsis (_("Bring the system down."));
	nih_option_set_help (
		_("TIME may have different formats, the most common is simply "
		  "the word 'now' which will bring the system down "
		  "immediately.  Other valid formats are +m, where m is the "
		  "number of minutes to wait until shutting down and hh:mm "
		  "which specifies the time on the 24hr clock.\n"
		  "\n"
		  "Logged in users are warned by a message sent to their "
		  "terminal, you may include an optional MESSAGE included "
		  "with this.  Messages can be sent without actually "
		  "bringing the system down by using the -k option.\n"
		  "\n"
		  "If TIME is given, the command will remain in the "
		  "foreground until the shutdown occurs.  It can be cancelled "
		  "by Control-C, or by another user using the -c option.\n"
		  "\n"
		  "The system is brought down into maintenance (single-user) "
		  "mode by default, you can change this with either the -r or "
		  "-h option which specify a reboot or system halt "
		  "respectively.  The -h option can be further modified with "
		  "-H or -P to specify whether to halt the system, or to "
		  "power it off afterwards.  The default is left up to the "
		  "shutdown scripts."));

	args = nih_option_parser (NULL, argc, argv, options, FALSE);
	if (! args)
		exit (1);

	/* If the runlevel wasn't given explicitly, set it to 1 so we go
	 * down into single-user mode.
	 */
	if (! runlevel) {
		runlevel = '1';
		init_halt = NULL;
	}


	/* When may be specified with -g, or must be first argument */
	if (! (cancel || when || args[0])) {
		fprintf (stderr, _("%s: time expected\n"), program_name);
		nih_main_suggest_help ();
		exit (1);
	} else if (! (cancel || when)) {
		when = NIH_MUST (nih_strdup (NULL, args[0]));
		arg = 1;
	} else {
		arg = 0;
	}

	/* Parse the time argument */
	if (when) {
		if (! strcmp (when, "now")) {
			/* "now" means, err, now */
			delay = 0;
		} else if (strchr (when, ':')) {
			/* Clock time */
			long       hours, mins;
			char      *endptr;
			struct tm *tm;
			time_t     now;

			hours = strtoul (when, &endptr, 10);
			if ((*endptr != ':') || (hours < 0) || (hours > 23)) {
				fprintf (stderr, _("%s: illegal hour value\n"),
					 program_name);
				nih_main_suggest_help ();
				exit (1);
			}

			mins = strtoul (endptr + 1, &endptr, 10);
			if (*endptr || (mins < 0) || (mins > 59)) {
				fprintf (stderr,
					 _("%s: illegal minute value\n"),
					 program_name);
				nih_main_suggest_help ();
				exit (1);
			}

			/* Subtract the current time to get the delay.
			 * Add a whole day if we go negative */
			now = time (NULL);
			tm = localtime (&now);
			delay = (((hours * 60) + mins)
				 - ((tm->tm_hour * 60) + tm->tm_min));
			if (delay < 0)
				delay += 1440;
		} else {
			/* Delay in minutes */
			char *endptr;

			delay = strtoul (when, &endptr, 10);
			if (*endptr || (delay < 0)) {
				fprintf (stderr, _("%s: illegal time value\n"),
					 program_name);
				nih_main_suggest_help ();
				exit (1);
			}
		}
		nih_free (when);
	}


	/* The rest of the arguments are a message.
	 * Really this should be just the next argument, but that's not
	 * how this has been traditionally done *sigh*
	 */
	message = NIH_MUST (nih_strdup (NULL, ""));
	messagelen = 0;
	for (; args[arg]; arg++) {
		message = NIH_MUST (nih_realloc (
				  message, NULL,
				  messagelen + strlen(args[arg]) + 4));

		strcat (message, args[arg]);
		strcat (message, " ");
		messagelen += strlen (args[arg]) + 1;
	}

	/* Terminate with \r\n */
	if (messagelen)
		strcat (message, "\r\n");


	/* Check we're root, or setuid root */
	setuid (geteuid ());
	if (getuid ()) {
		nih_fatal (_("Need to be root"));
		exit (1);
	}

	/* Look for an existing pid file and deal with the existing
	 * process if there is one.
	 */
	pid = nih_main_read_pidfile ();
	if (pid > 0) {
		if (cancel) {
			if (kill (pid, SIGINT) < 0) {
				nih_error (_("Shutdown is not running"));
				exit (1);
			}

			if (messagelen)
				wall (message);

			exit (0);
		} else if (kill (pid, 0) == 0) {
			nih_error (_("Another shutdown is already running"));
			exit (1);
		}
	} else if (cancel) {
		nih_error (_("Cannot find pid of running shutdown"));
		exit (1);
	}

	/* Send an initial message */
	msg = NIH_MUST (warning_message (message));
	wall (msg);

	if (warn_only)
		exit (0);


	/* Give us a sane environment */
	if (chdir ("/") < 0)
		nih_warn ("%s: %s", _("Unable to change directory"),
			  strerror (errno));
	umask (022);

	/* Shutdown now? */
	if (! delay)
		shutdown_now ();

	/* Save our pid so we can be interrupted later */
	if (nih_main_write_pidfile (getpid ()) < 0) {
		NihError *err;

		err = nih_error_get ();
		nih_warn ("%s: %s: %s", nih_main_get_pidfile(),
			  _("Unable to write pid file"), err->message);
		nih_free (err);
	}


	/* Ignore a whole bunch of signals */
	nih_signal_set_ignore (SIGCHLD);
	nih_signal_set_ignore (SIGHUP);
	nih_signal_set_ignore (SIGTSTP);
	nih_signal_set_ignore (SIGTTIN);
	nih_signal_set_ignore (SIGTTOU);

	/* Catch the usual quit signals */
	nih_signal_set_handler (SIGINT, nih_signal_handler);
	NIH_MUST (nih_signal_add_handler (NULL, SIGINT,
					  cancel_callback, NULL));
	nih_signal_set_handler (SIGQUIT, nih_signal_handler);
	NIH_MUST (nih_signal_add_handler (NULL, SIGQUIT,
					  cancel_callback, NULL));
	nih_signal_set_handler (SIGTERM, nih_signal_handler);
	NIH_MUST (nih_signal_add_handler (NULL, SIGTERM,
					  cancel_callback, NULL));

	/* Call a timer every minute until we shutdown */
	NIH_MUST (nih_timer_add_periodic (NULL, 60,
					  (NihTimerCb)timer_callback,
					  message));

	/* Hang around */
	nih_main_loop ();

	return 0;
}