#define _BSD_SOURCE /* for daemon(3) */
+#ifdef HAVE_WINDOWS_H
+# include <windows.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <getopt.h>
-#include <netdb.h>
#include <sys/param.h>
-#include <sys/select.h>
#include <sys/types.h>
-#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
-#include <printf.h>
+#include <netdb.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#ifdef HAVE_PRINTF_H
+# include <printf.h>
+#endif
+#include "sockets.h"
#include "c-ctype.h"
#include "ignore-value.h"
+#include "error.h"
#include "daemon.h"
#define GUESTFWD_ADDR "10.0.2.4"
#define GUESTFWD_PORT "6666"
+/* This is only a hint. If not defined, ignore it. */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
int verbose = 0;
static int print_shell_quote (FILE *stream, const struct printf_info *info, const void *const *args);
#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)
{
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);
case '?':
usage ();
- exit (0);
+ exit (EXIT_SUCCESS);
default:
fprintf (stderr, "guestfsd: unexpected command line option 0x%x\n", c);
- exit (1);
+ exit (EXIT_FAILURE);
}
}
if (optind < argc) {
usage ();
- exit (1);
+ exit (EXIT_FAILURE);
}
cmdline = read_cmdline ();
printf ("could not read linux command line\n");
}
+#ifndef WIN32
/* Make sure SIGPIPE doesn't kill us. */
struct sigaction sa;
memset (&sa, 0, sizeof sa);
sa.sa_flags = 0;
if (sigaction (SIGPIPE, &sa, NULL) == -1)
perror ("sigaction SIGPIPE"); /* but try to continue anyway ... */
+#endif
+#ifdef WIN32
+# 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
setenv ("SHELL", "/bin/sh", 1);
setenv ("LC_ALL", "C", 1);
+#ifndef WIN32
/* We document that umask defaults to 022 (it should be this anyway). */
umask (022);
+#else
+ /* This is the default for Windows anyway. It's not even clear if
+ * Windows ever uses this -- the MSDN documentation for the function
+ * contains obvious errors.
+ */
+ _umask (0);
+#endif
/* Get the vmchannel string.
*
vmchannel = strndup (p + 18, len);
if (!vmchannel) {
perror ("strndup");
- exit (1);
+ exit (EXIT_FAILURE);
}
}
vmchannel = strndup (p + 4, len);
if (!vmchannel) {
perror ("strndup");
- exit (1);
+ exit (EXIT_FAILURE);
}
memcpy (vmchannel, "tcp:", 4);
}
vmchannel = strdup ("tcp:" GUESTFWD_ADDR ":" GUESTFWD_PORT);
if (!vmchannel) {
perror ("strdup");
- exit (1);
+ exit (EXIT_FAILURE);
}
}
/* Connect to vmchannel. */
int sock = -1;
- if (strncmp (vmchannel, "tcp:", 4) == 0) {
+ if (STREQLEN (vmchannel, "tcp:", 4)) {
/* Resolve the hostname. */
struct addrinfo *res, *rr;
struct addrinfo hints;
} else {
fprintf (stderr, "vmchannel: expecting \"tcp:<ip>:<port>\": %s\n",
vmchannel);
- exit (1);
+ exit (EXIT_FAILURE);
}
memset (&hints, 0, sizeof hints);
if (r != 0) {
fprintf (stderr, "%s:%s: %s\n",
host, port, gai_strerror (r));
- exit (1);
+ exit (EXIT_FAILURE);
}
/* Connect to the given TCP socket. */
"unknown vmchannel connection type: %s\n"
"expecting \"tcp:<ip>:<port>\"\n",
vmchannel);
- exit (1);
+ exit (EXIT_FAILURE);
}
if (sock == -1) {
"or on the libguestfs redhat com mailing list.\n"
"\n",
vmchannel);
- exit (1);
+ exit (EXIT_FAILURE);
}
/* Send the magic length message which indicates that
XDR xdr;
uint32_t len = GUESTFS_LAUNCH_FLAG;
xdrmem_create (&xdr, lenbuf, sizeof lenbuf, XDR_ENCODE);
- xdr_uint32_t (&xdr, &len);
+ xdr_u_int (&xdr, &len);
if (xwrite (sock, lenbuf, sizeof lenbuf) == -1)
- exit (1);
+ exit (EXIT_FAILURE);
xdr_destroy (&xdr);
if (!dont_fork) {
if (daemon (0, 1) == -1) {
perror ("daemon");
- exit (1);
+ exit (EXIT_FAILURE);
}
}
/* Enter the main loop, reading and performing actions. */
main_loop (sock);
- exit (0);
+ exit (EXIT_SUCCESS);
}
/* Read /proc/cmdline. */
int size = 0, alloc = 0;
char *p, *pend;
- if (strcmp (str, "") == 0)
+ if (STREQ (str, ""))
goto empty_list;
p = 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.
*/
* 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)
{
- command (NULL, NULL, "/sbin/udevadm", "settle", NULL);
+ (void) command (NULL, NULL, "/sbin/udevadm", "settle", NULL);
+ (void) command (NULL, NULL, "/sbin/udevsettle", NULL);
}