X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fgenerator.ml;h=19de0b7a4aef098c20501cafc4c19257bbd76cd1;hp=b0f95436c739575fcceab70110fa49e59c891054;hb=59b487b7dd9db0dd6f262ca4b39c471c7d6cfa53;hpb=7f2ac369f7747a033f5e84d8c7fb3aa131f25537 diff --git a/src/generator.ml b/src/generator.ml index b0f9543..19de0b7 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -805,6 +805,32 @@ is passed to the appliance at boot time. See C. For more information on the architecture of libguestfs, see L."); + ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"], + [InitNone, Always, TestOutputFalse ( + [["set_trace"; "false"]; + ["get_trace"]])], + "enable or disable command traces", + "\ +If the command trace flag is set to 1, then commands are +printed on stdout before they are executed in a format +which is very similar to the one used by guestfish. In +other words, you can run a program with this enabled, and +you will get out a script which you can feed to guestfish +to perform the same set of actions. + +If you want to trace C API calls into libguestfs (and +other libraries) then possibly a better way is to use +the external ltrace(1) command. + +Command traces are disabled unless the environment variable +C is defined and set to C<1>."); + + ("get_trace", (RBool "trace", []), -1, [], + [], + "get command trace enabled flag", + "\ +Return the command trace flag."); + ] (* daemon_functions are any functions which cause some action @@ -4643,6 +4669,52 @@ check_state (guestfs_h *g, const char *caller) "; + (* Generate code to generate guestfish call traces. *) + let trace_call shortname style = + pr " if (guestfs__get_trace (g)) {\n"; + + let needs_i = + List.exists (function + | StringList _ | DeviceList _ -> true + | _ -> false) (snd style) in + if needs_i then ( + pr " int i;\n"; + pr "\n" + ); + + pr " printf (\"%s\");\n" shortname; + List.iter ( + function + | String n (* strings *) + | Device n + | Pathname n + | Dev_or_Path n + | FileIn n + | FileOut n -> + (* guestfish doesn't support string escaping, so neither do we *) + pr " printf (\" \\\"%%s\\\"\", %s);\n" n + | OptString n -> (* string option *) + pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n; + pr " else printf (\" null\");\n" + | StringList n + | DeviceList n -> (* string list *) + pr " putchar (' ');\n"; + pr " putchar ('\"');\n"; + pr " for (i = 0; %s[i]; ++i) {\n" n; + pr " if (i > 0) putchar (' ');\n"; + pr " fputs (%s[i], stdout);\n" n; + pr " }\n"; + pr " putchar ('\"');\n"; + | Bool n -> (* boolean *) + pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n + | Int n -> (* int *) + pr " printf (\" %%d\", %s);\n" n + ) (snd style); + pr " putchar ('\\n');\n"; + pr " }\n"; + pr "\n"; + in + (* For non-daemon functions, generate a wrapper around each function. *) List.iter ( fun (shortname, style, _, _, _, _, _) -> @@ -4651,6 +4723,7 @@ check_state (guestfs_h *g, const char *caller) generate_prototype ~extern:false ~semicolon:false ~newline:true ~handle:"g" name style; pr "{\n"; + trace_call shortname style; pr " return guestfs__%s " shortname; generate_c_call_args ~handle:"g" style; pr ";\n"; @@ -4758,6 +4831,7 @@ check_state (guestfs_h *g, const char *caller) pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n"; pr " int serial;\n"; pr "\n"; + trace_call shortname style; pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code; pr " guestfs_set_busy (g);\n"; pr "\n"; @@ -6288,7 +6362,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 ->