X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fguestfsd.c;h=69baf9e845010f139700927a40d3159e569200cd;hp=d3b754d255b26f384e10a6677a12f8f60c57f530;hb=2bec01ba1fcceb4880aa991e599920be9b68996a;hpb=8d0d8cd4a340dea6fd3d84ab5b361aa757d5e19e diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index d3b754d..69baf9e 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -21,7 +21,7 @@ #define _BSD_SOURCE /* for daemon(3) */ #ifdef HAVE_WINDOWS_H -#include +# include #endif #include @@ -39,13 +39,17 @@ #include #include #include +#include +#include #ifdef HAVE_PRINTF_H -#include +# include #endif +#include "sockets.h" #include "c-ctype.h" #include "ignore-value.h" +#include "error.h" #include "daemon.h" @@ -57,7 +61,11 @@ static char *read_cmdline (void); /* This is only a hint. If not defined, ignore it. */ #ifndef AI_ADDRCONFIG -#define AI_ADDRCONFIG 0 +# define AI_ADDRCONFIG 0 +#endif + +#ifndef MAX +# define MAX(a,b) ((a)>(b)?(a):(b)) #endif int verbose = 0; @@ -74,10 +82,42 @@ static int print_arginfo (const struct printf_info *info, size_t n, int *argtype #endif #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; + + /* http://msdn2.microsoft.com/en-us/library/ms742213.aspx */ + r = gl_sockets_startup (SOCKETS_2_2); + return r == 0 ? 0 : -1; +} +#else /* !WIN32 */ +static int +winsock_init (void) +{ + return 0; +} +#endif /* !WIN32 */ + /* Location to mount root device. */ const char *sysroot = "/sysroot"; /* No trailing slash. */ int sysroot_len = 8; +/* Not used explicitly, but required by the gnulib 'error' module. */ +const char *program_name = "guestfsd"; + static void usage (void) { @@ -101,6 +141,9 @@ main (int argc, char *argv[]) char *cmdline; char *vmchannel = NULL; + if (winsock_init () == -1) + error (EXIT_FAILURE, 0, "winsock initialization failed"); + #ifdef HAVE_REGISTER_PRINTF_SPECIFIER /* http://udrepper.livejournal.com/20948.html */ register_printf_specifier ('Q', print_shell_quote, print_arginfo); @@ -172,15 +215,19 @@ main (int argc, char *argv[]) #endif #ifdef WIN32 -#define setenv(n,v,f) _putenv(n "=" v) +# define setenv(n,v,f) _putenv(n "=" v) #endif /* Set up a basic environment. After we are called by /init the * environment is essentially empty. * https://bugzilla.redhat.com/show_bug.cgi?id=502074#c5 + * + * NOTE: if you change $PATH, you must also change 'prog_exists' + * function below. */ - setenv ("PATH", "/usr/bin:/bin", 1); + setenv ("PATH", "/sbin:/usr/sbin:/bin:/usr/bin", 1); setenv ("SHELL", "/bin/sh", 1); setenv ("LC_ALL", "C", 1); + setenv ("TERM", "dumb", 1); #ifndef WIN32 /* We document that umask defaults to 022 (it should be this anyway). */ @@ -335,15 +382,10 @@ main (int argc, char *argv[]) /* Fork into the background. */ if (!dont_fork) { -#ifndef WIN32 if (daemon (0, 1) == -1) { perror ("daemon"); exit (EXIT_FAILURE); } -#else /* WIN32 */ - 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 */ } /* Enter the main loop, reading and performing actions. */ @@ -890,6 +932,28 @@ split_lines (char *str) return lines; } +/* Skip leading and trailing whitespace, updating the original string + * in-place. + */ +void +trim (char *str) +{ + size_t len = strlen (str); + + while (len > 0 && c_isspace (str[len-1])) { + str[len-1] = '\0'; + len--; + } + + const char *p = str; + while (*p && c_isspace (*p)) { + p++; + len--; + } + + memmove (str, p, len+1); +} + /* printf helper function so we can use %Q ("quoted") and %R to print * shell-quoted strings. See HACKING file for more details. */ @@ -996,35 +1060,42 @@ device_name_translation (char *device, const char *func) goto error; } +/* Check program exists and is executable on $PATH. Actually, we + * just assume PATH contains the default entries (see main() above). + */ +int +prog_exists (const char *prog) +{ + static const char * const dirs[] = + { "/sbin", "/usr/sbin", "/bin", "/usr/bin" }; + size_t i; + char buf[1024]; + + for (i = 0; i < sizeof dirs / sizeof dirs[0]; ++i) { + snprintf (buf, sizeof buf, "%s/%s", dirs[i], prog); + if (access (buf, X_OK) == 0) + return 1; + } + return 0; +} + /* LVM and other commands aren't synchronous, especially when udev is * involved. eg. You can create or remove some device, but the /dev * device node won't appear until some time later. This means that * you get an error if you run one command followed by another. + * * Use 'udevadm settle' after certain commands, but don't be too * fussed if it fails. + * + * 'udevsettle' was the old name for this command (RHEL 5). This was + * deprecated in favour of 'udevadm settle'. The old 'udevsettle' + * command was left as a symlink. Then in Fedora 13 the old symlink + * remained but it stopped working (RHBZ#548121), so we have to be + * careful not to assume that we can use 'udevsettle' if it exists. */ void udev_settle (void) { - static int which_prog = 0; - - if (which_prog == 0) { - if (access ("/sbin/udevsettle", X_OK) == 0) - which_prog = 2; - else if (access ("/sbin/udevadm", X_OK) == 0) - which_prog = 1; - else - which_prog = 3; - } - - switch (which_prog) { - case 1: - command (NULL, NULL, "/sbin/udevadm", "settle", NULL); - break; - case 2: - command (NULL, NULL, "/sbin/udevsettle", NULL); - break; - default: - ; - } + (void) command (NULL, NULL, "udevadm", "settle", NULL); + (void) command (NULL, NULL, "udevsettle", NULL); }