/* libguestfs - the guestfsd daemon
- * Copyright (C) 2009-2010 Red Hat Inc.
+ * Copyright (C) 2009-2011 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <config.h>
-#define _BSD_SOURCE /* for daemon(3) */
-
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#ifdef WIN32
static int
-daemon (int nochdir, int noclose)
-{
- fprintf (stderr,
- "On Windows the daemon does not support forking into the "
- "background.\nYou *must* run the daemon with the -f option.\n");
- exit (EXIT_FAILURE);
-}
-#endif /* WIN32 */
-
-#ifdef WIN32
-static int
winsock_init (void)
{
int r;
/* Location to mount root device. */
const char *sysroot = "/sysroot"; /* No trailing slash. */
-int sysroot_len = 8;
+size_t sysroot_len = 8;
+
+/* If set (the default), do 'umount-all' when performing autosync. */
+int autosync_umount = 1;
/* Not used explicitly, but required by the gnulib 'error' module. */
const char *program_name = "guestfsd";
+/* Name of the virtio-serial channel. */
+#define VIRTIO_SERIAL_CHANNEL "/dev/virtio-ports/org.libguestfs.channel.0"
+
static void
usage (void)
{
fprintf (stderr,
- "guestfsd [-f|--foreground] [-v|--verbose]\n");
+ "guestfsd [-r] [-v|--verbose]\n");
}
int
main (int argc, char *argv[])
{
- static const char *options = "fv?";
+ static const char *options = "rv?";
static const struct option long_options[] = {
- { "foreground", 0, 0, 'f' },
{ "help", 0, 0, '?' },
{ "verbose", 0, 0, 'v' },
{ 0, 0, 0, 0 }
};
int c;
- int dont_fork = 0;
char *cmdline;
- chdir ("/");
+ ignore_value (chdir ("/"));
if (winsock_init () == -1)
error (EXIT_FAILURE, 0, "winsock initialization failed");
if (c == -1) break;
switch (c) {
- case 'f':
- dont_fork = 1;
+ /* The -r flag is used when running standalone. It changes
+ * several aspects of the daemon.
+ */
+ case 'r':
+ sysroot = "";
+ sysroot_len = 0;
+ autosync_umount = 0;
break;
case 'v':
_umask (0);
#endif
+ /* Make a private copy of /etc/lvm so we can change the config (see
+ * daemon/lvm-filter.c).
+ */
+ copy_lvm ();
+
/* Connect to virtio-serial channel. */
- int sock = open ("/dev/virtio-ports/org.libguestfs.channel.0",
- O_RDWR | O_CLOEXEC);
+ int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR | O_CLOEXEC);
if (sock == -1) {
fprintf (stderr,
"\n"
"output to the libguestfs developers, either in a bug report\n"
"or on the libguestfs redhat com mailing list.\n"
"\n");
- perror ("/dev/virtio-ports/org.libguestfs.channel.0");
+ perror (VIRTIO_SERIAL_CHANNEL);
exit (EXIT_FAILURE);
}
xdr_destroy (&xdr);
- /* Fork into the background. */
- if (!dont_fork) {
- if (daemon (0, 1) == -1) {
- perror ("daemon");
- exit (EXIT_FAILURE);
- }
- }
-
/* Enter the main loop, reading and performing actions. */
main_loop (sock);
}
int
-add_string (char ***argv, int *size, int *alloc, const char *str)
+add_string_nodup (char ***argv, int *size, int *alloc, char *str)
{
char **new_argv;
- char *new_str;
if (*size >= *alloc) {
*alloc += 64;
if (new_argv == NULL) {
reply_with_perror ("realloc");
free_strings (*argv);
+ *argv = NULL;
return -1;
}
*argv = new_argv;
}
+ (*argv)[*size] = str;
+
+ (*size)++;
+ return 0;
+}
+
+int
+add_string (char ***argv, int *size, int *alloc, const char *str)
+{
+ char *new_str;
+
if (str) {
new_str = strdup (str);
if (new_str == NULL) {
reply_with_perror ("strdup");
free_strings (*argv);
+ *argv = NULL;
+ return -1;
}
- } else
+ } else {
new_str = NULL;
+ }
- (*argv)[*size] = new_str;
-
- (*size)++;
- return 0;
+ return add_string_nodup (argv, size, alloc, new_str);
}
size_t
}
if (pid == 0) { /* Child process running the command. */
+ signal (SIGALRM, SIG_DFL);
+ signal (SIGPIPE, SIG_DFL);
close (0);
if (flag_copy_stdin) {
dup2 (stdin_fd[0], 0);
close (stdin_fd[1]);
} else {
/* Set stdin to /dev/null (ignore failure) */
- open ("/dev/null", O_RDONLY);
+ ignore_value (open ("/dev/null", O_RDONLY));
}
close (so_fd[0]);
close (se_fd[0]);
quit = 0;
while (quit < 2) {
+ again:
rset2 = rset;
r = select (MAX (so_fd[0], se_fd[0]) + 1, &rset2, NULL, NULL, NULL);
if (r == -1) {
+ if (errno == EINTR)
+ goto again;
+
perror ("select");
quit:
- if (stdoutput) free (*stdoutput);
- if (stderror) free (*stderror);
+ if (stdoutput) {
+ free (*stdoutput);
+ *stdoutput = NULL;
+ }
+ if (stderror) {
+ free (*stderror);
+ /* Need to return non-NULL *stderror here since most callers
+ * will try to print and then free the err string.
+ * Unfortunately recovery from strdup failure here is not
+ * possible.
+ */
+ *stderror = strdup ("error running external command, "
+ "see debug output for details");
+ }
close (so_fd[0]);
close (se_fd[0]);
waitpid (pid, NULL, 0);