[PATCH] Add echo_daemon command
by Matthew Booth
echo_daemon is a simple echo which can be used to test connectivity between the
client and daemon.
---
daemon/Makefile.am | 1 +
daemon/echo_daemon.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
daemon/m4/stddef_h.m4 | 45 +++++++++++++++++++++++++++++++++
po/POTFILES.in | 1 +
src/MAX_PROC_NR | 2 +-
src/generator.ml | 7 +++++
6 files changed, 121 insertions(+), 1 deletions(-)
create mode 100644 daemon/echo_daemon.c
create mode 100644 daemon/m4/stddef_h.m4
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 83ee408..ae74699 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -36,6 +36,7 @@ guestfsd_SOURCES = \
dmesg.c \
dropcaches.c \
du.c \
+ echo_daemon.c \
ext2.c \
fallocate.c \
file.c \
diff --git a/daemon/echo_daemon.c b/daemon/echo_daemon.c
new file mode 100644
index 0000000..dbede2f
--- /dev/null
+++ b/daemon/echo_daemon.c
@@ -0,0 +1,66 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2009 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "actions.h"
+
+char *
+do_echo_daemon (char *const *argv)
+{
+ char *out = NULL;
+ size_t out_len = 0;
+
+ /* Iterate over argv entries until reaching the NULL terminator */
+ while (*argv) {
+ char add_space = 0;
+
+ /* Store the end of current output */
+ size_t out_end = out_len;
+
+ /* Calculate the new output size */
+ size_t arg_len = strlen(*argv);
+ out_len += arg_len;
+
+ /* We will prepend a space if this isn't the first argument added */
+ if (NULL != out) {
+ out_len++;
+ add_space = 1;
+ }
+
+ /* Make the output buffer big enough for the string and its terminator */
+ out = realloc (out, out_len + 1);
+
+ /* Prepend a space if required */
+ if (add_space) {
+ out[out_end++] = ' ';
+ }
+
+ /* Copy the argument to the output */
+ memcpy(&out[out_end], *argv, arg_len);
+
+ argv++;
+ }
+
+ /* NULL terminate the output */
+ out[out_len] = '\0';
+
+ return out;
+}
diff --git a/daemon/m4/stddef_h.m4 b/daemon/m4/stddef_h.m4
new file mode 100644
index 0000000..682e9c6
--- /dev/null
+++ b/daemon/m4/stddef_h.m4
@@ -0,0 +1,45 @@
+dnl A placeholder for POSIX 2008 <stddef.h>, for platforms that have issues.
+# stddef_h.m4 serial 1
+dnl Copyright (C) 2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_STDDEF_H],
+[
+ AC_REQUIRE([gl_STDDEF_H_DEFAULTS])
+ AC_REQUIRE([gt_TYPE_WCHAR_T])
+ if test $gt_cv_c_wchar_t = no; then
+ HAVE_WCHAR_T=0
+ STDDEF_H=stddef.h
+ fi
+ AC_CACHE_CHECK([whether NULL can be used in arbitrary expressions],
+ [gl_cv_decl_null_works],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stddef.h>
+ int test[2 * (sizeof NULL == sizeof (void *)) -1];
+]])],
+ [gl_cv_decl_null_works=yes],
+ [gl_cv_decl_null_works=no])])
+ if test $gl_cv_decl_null_works = no; then
+ REPLACE_NULL=1
+ STDDEF_H=stddef.h
+ fi
+ if test -n "$STDDEF_H"; then
+ gl_CHECK_NEXT_HEADERS([stddef.h])
+ fi
+])
+
+AC_DEFUN([gl_STDDEF_MODULE_INDICATOR],
+[
+ dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+ AC_REQUIRE([gl_STDDEF_H_DEFAULTS])
+ GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_STDDEF_H_DEFAULTS],
+[
+ dnl Assume proper GNU behavior unless another module says otherwise.
+ REPLACE_NULL=0; AC_SUBST([REPLACE_NULL])
+ HAVE_WCHAR_T=1; AC_SUBST([HAVE_WCHAR_T])
+ STDDEF_H=''; AC_SUBST([STDDEF_H])
+])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1b2f82a..44e472b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ daemon/dir.c
daemon/dmesg.c
daemon/dropcaches.c
daemon/du.c
+daemon/echo_daemon.c
daemon/ext2.c
daemon/fallocate.c
daemon/file.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 205a12b..6bb2f98 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-194
+195
diff --git a/src/generator.ml b/src/generator.ml
index 439c9c4..f820e1f 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -3595,6 +3595,13 @@ This loads a kernel module in the appliance.
The kernel module must have been whitelisted when libguestfs
was built (see C<appliance/kmod.whitelist.in> in the source).");
+ ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
+ [InitNone, Always, TestRun [["echo_daemon"; "\"This is a test\""]]],
+ "echo arguments back to the client",
+ "\
+This commands works much like the unix echo command. It returns its arguments as
+a string.");
+
]
let all_functions = non_daemon_functions @ daemon_functions
--
1.6.2.5
15 years
[FOR REVIEW ONLY] guestfish: Enable grouping in string lists
by Matthew Booth
This patch lacks updated documentation and tests.
This change adds the ability to group entries in a string list with single
quotes. So the string:
"'foo bar'"
becomes 1 token rather than 2. Consequently single quotes must now be escaped:
"\'"
resolves to a literal single quote.
Incidentally, this change also alters another, probably unintentional behaviour
of the previous implementation, in that tokens are separated by any amount of
whitespace rather than a single whitespace character. I.e.:
"a b"
resolves to:
'a' 'b'
rather than:
'a' '' 'b'
Whitespace is now also defined to include tabs.
parse_string_list can also now fail if it contains an unmatched open quote.
---
fish/fish.c | 129 +++++++++++++++++++++++++++++++++++++++++++++--------
src/generator.ml | 3 +-
2 files changed, 111 insertions(+), 21 deletions(-)
diff --git a/fish/fish.c b/fish/fish.c
index a4069d6..62ec3a3 100644
--- a/fish/fish.c
+++ b/fish/fish.c
@@ -1082,30 +1082,119 @@ is_true (const char *str)
strcasecmp (str, "no") != 0;
}
-/* XXX We could improve list parsing. */
char **
parse_string_list (const char *str)
{
- char **argv;
- const char *p, *pend;
- int argc, i;
-
- argc = 1;
- for (i = 0; str[i]; ++i)
- if (str[i] == ' ') argc++;
-
- argv = malloc (sizeof (char *) * (argc+1));
- if (argv == NULL) { perror ("malloc"); exit (1); }
-
- p = str;
- i = 0;
- while (*p) {
- pend = strchrnul (p, ' ');
- argv[i] = strndup (p, pend-p);
- i++;
- p = *pend == ' ' ? pend+1 : pend;
+ char **argv = NULL;
+ size_t argv_i = 0;
+
+ /* Current position pointer */
+ const char *p = str;
+
+ /* Token might be simple:
+ * Token
+ * or be quoted:
+ * 'This is a single token'
+ * or contain embedded single-quoted sections:
+ * This' is a sing'l'e to'ken
+ *
+ * The latter may seem over-complicated, but it's what a normal shell does.
+ * Not doing it risks surprising somebody.
+ *
+ * This outer loop is over complete tokens.
+ */
+ while(*p) {
+ char *tok = NULL;
+ size_t tok_len = 0;
+
+ /* Skip leading whitespace */
+ p += strspn (p, " \t");
+
+ char in_quote = 0;
+
+ /* This loop is over token 'fragments'. A token can be in multiple bits if
+ * it contains single quotes. We also treat a both sides of an escaped quote
+ * as separate fragments because we can't just copy it: we have to remove
+ * the \.
+ */
+ while (*p && (!isblank (*p) || in_quote)) {
+ const char *end = p;
+
+ /* Check if the fragment starts with a quote */
+ if ('\'' == *p) {
+ /* Toggle in_quote */
+ in_quote = !in_quote;
+
+ /* Skip the quote */
+ p++; end++;
+ }
+
+ /* If we're in a quote, look for an end quote */
+ if (in_quote) {
+ end += strcspn (end, "'");
+ }
+
+ /* Otherwise, look for whitespace or a quote */
+ else {
+ end += strcspn (end, " \t'");
+ }
+
+ /* Grow the token to accommodate the fragment */
+ char *tok_end = tok_len == 0 ? NULL : tok + tok_len;
+ tok_len += end - p;
+ tok = realloc (tok, tok_len + 1);
+ if (NULL == tok) { perror ("realloc"); exit (1); }
+ if (NULL == tok_end) tok_end = tok;
+
+ /* Check if we stopped on an escaped quote */
+ if ('\'' == *end && end != p && *(end-1) == '\\') {
+ /* Add everything before \' to the token */
+ memcpy (tok_end, p, end - p - 1);
+
+ /* Add the ' */
+ tok[tok_len-1] = '\'';
+
+ /* Already processed the quote */
+ p = end + 1;
+ }
+
+ else {
+ /* Add the whole fragment */
+ memcpy (tok_end, p, end - p);
+
+ p = end;
+ }
+ }
+
+ /* We've reached the end of a token. We shouldn't still be in quotes. */
+ if (in_quote) {
+ fprintf(stderr, _("Runaway quote in string \"%s\"\n"), str);
+
+ size_t i;
+ for (i = 0; i < argv_i; i++) {
+ free (argv[i]);
+ }
+ free(argv);
+
+ return NULL;
+ }
+
+ /* Add this token if there is one. There might not be if there was
+ * whitespace at the end of the input string */
+ if(tok) {
+ /* Add the NULL terminator */
+ tok[tok_len] = '\0';
+
+ /* Add the argument to the argument list */
+ argv = realloc(argv, sizeof(*argv) * argv_i + 1);
+ argv[argv_i] = tok;
+ argv_i++;
+ }
}
- argv[i] = NULL;
+
+ /* NULL terminate the argument list */
+ argv = realloc(argv, sizeof(*argv) * argv_i + 1);
+ argv[argv_i] = NULL;
return argv;
}
diff --git a/src/generator.ml b/src/generator.ml
index 5cf6a94..7571f95 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -6348,7 +6348,8 @@ and generate_fish_cmds () =
pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
name i i
| StringList name | DeviceList name ->
- pr " %s = parse_string_list (argv[%d]);\n" name i
+ pr " %s = parse_string_list (argv[%d]);\n" name i;
+ pr " if (%s == NULL) return -1;\n" name;
| Bool name ->
pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
| Int name ->
--
1.6.2.5
15 years
[PATCH] Non-daemon actions indirect through generated code
by Richard W.M. Jones
Matt asked me this morning if we could generate guestfish scripts
automatically from running programs like virt-v2v. Good idea.
This patch however doesn't do this, but it lays the groundwork for it:
In order for us to generate code for any functions which don't go
through the daemon, we need to add an indirection to those calls via
some generated code. This will allow us to add guestfish tracing at
some point in the future.
If you want to debug calls to libguestfs code, then the easiest thing
to do is to use ltrace(1). Sample ltrace output is attached.
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
15 years
Perl module versioning
by Richard W.M. Jones
Re:
https://bugzilla.redhat.com/show_bug.cgi?id=521674
Perl modules are unversioned, but should carry version numbers
Currently perl RPM deps are unversioned. Apparently if we add a
version number into the perl module(s) then we can fix that, eg:
our $VERSION = "1.0.68";
This would allow Perl users to specify the version either through an
RPM dependency or in code like this:
use Sys::Guestfs 1.0.68;
The file in question (perl/lib/Sys/Guestfs.pm) is generated. Up to
this point I have resisted putting the version number into any
generated files. One reason is that it's unnecessary churn for those
files. Another is that we shouldn't encourage users to depend on
specific versions (instead, they should test for required features).
Another is that the version of Sys::Guestfs doesn't really tell you
what is available in the dynamically-loaded libguestfs.so, nor in the
daemon/appliance.
Worked example:
Your program needs $g->zerofree.
(1) May or may not exist in the Perl library.
(2) May or may not exist in the C API (libguestfs.so).
(3) May or may not exist in the daemon (stubs.c:zerofree_stub)
(4) May or may not have been added to the appliance (/usr/bin/zerofree)
Since so much can potentially go wrong, I think the only realistic
solution is along these lines:
eval { $g->zerofree(...) }; die "zerofree failed: $@" if $@;
Do other languages offer equivalent runtime detection? [OCaml - no]
How do we ensure in RPM/dpkg that a consistent set of packages are
installed? RPM only "knows" version numbers, unless we export lots of
fine-grained dependencies. So far the solution has been to depend on
the C library, like:
Requires: libguestfs >= 1.0.68
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
15 years
install error from epel ?
by Jeremy Eder
has anyone seen this on a 64bit rhel box:
root@lab: ~ # yum --enablerepo=epel-testing install guestfish '*guestfs*'
Transaction Check Error:
file /usr/bin/libguestfs-supermin-helper from install of libguestfs-1.0.67-1.el5.i386 conflicts with file from package libguestfs-1.0.67-1.el5.x86_64
Linux lab.lab 2.6.18-128.7.1.el5 #1 SMP Wed Aug 19 04:00:49 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Red Hat Enterprise Linux Server release 5.3 (Tikanga)
epel-release-5-3
--jer
15 years
[PATCH] internationalisation: Replace autopoint infrastructure with libintl-perl
by Matthew Booth
I noticed that virt-v2v, which is written exclusively in perl, failed to
generate virt-v2v.pot. After much head scratching I also noticed that
libguestfs.pot didn't include any messages from perl sources. Some reading of
libintl-perl shows that a somewhat more complicated xgettext command line is
required, as it doesn't understand Locale::TextDomain syntax by default. After a
little more head scratching, I decided to replace the autopoint generated
infrastructure with the reference infrastructure from libintl-perl because:
1. It works
2. It's a whole lot more transparent
libguestfs still needs some attention in this area. This change may not be
appropriate for libguestfs because it is not exclusively written in perl.
15 years