let functions = [
("mount", (Err, P2 (String "device", String "mountpoint")), 1,
- "Mount a guest disk at a position in the filesystem",
+ "mount a guest disk at a position in the filesystem",
"\
Mount a guest disk at a position in the filesystem. Block devices
are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
call, in order to improve reliability.");
("sync", (Err, P0), 2,
- "Sync disks, writes are flushed through to the disk image",
+ "sync disks, writes are flushed through to the disk image",
"\
This syncs the disk, so that any writes are flushed through to the
underlying disk image.
calling C<guestfs_close>.");
("touch", (Err, P1 (String "path")), 3,
- "Update file timestamps or create a new file",
+ "update file timestamps or create a new file",
"\
Touch acts like the L<touch(1)> command. It can be used to
-update the filesystems on a file, or, if the file does not exist,
+update the timestamps on a file, or, if the file does not exist,
to create a new zero-length file.");
]
| P1 arg1 -> f arg1
| P2 (arg1, arg2) -> f arg1; f arg2
+let iteri_args f = function
+ | P0 -> ()
+ | P1 arg1 -> f 0 arg1
+ | P2 (arg1, arg2) -> f 0 arg1; f 1 arg2
+
+let map_args f = function
+ | P0 -> []
+ | P1 arg1 -> [f arg1]
+ | P2 (arg1, arg2) -> [f arg1; f arg2]
+
+let nr_args = function | P0 -> 0 | P1 _ -> 1 | P2 _ -> 2
+
type comment_style = CStyle | HashStyle | OCamlStyle
type license = GPLv2 | LGPLv2
pr " serial = dispatch (g, GUESTFS_PROC_%s, NULL, NULL);\n"
(String.uppercase shortname)
| (_, args) ->
- pr "\n";
iter_args (
function
| String name -> pr " args.%s = (char *) %s;\n" name name
pr " default:\n";
pr " reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
pr " }\n";
+ pr "}\n"
+
+(* Generate a lot of different functions for guestfish. *)
+and generate_fish_cmds () =
+ generate_header CStyle GPLv2;
+
+ pr "#include <stdio.h>\n";
+ pr "#include <stdlib.h>\n";
+ pr "#include <string.h>\n";
+ pr "\n";
+ pr "#include \"fish.h\"\n";
+ pr "\n";
+
+ (* list_commands function, which implements guestfish -h *)
+ pr "void list_commands (void)\n";
+ pr "{\n";
+ pr " printf (\" %%-16s %%s\\n\", \"Command\", \"Description\");\n";
+ pr " list_builtin_commands ();\n";
+ List.iter (
+ fun (name, _, _, shortdesc, _) ->
+ pr " printf (\"%%-20s %%s\\n\", \"%s\", \"%s\");\n"
+ name shortdesc
+ ) functions;
+ pr " printf (\" Use -h <cmd> / help <cmd> to show detailed help for a command.\\n\");\n";
+ pr "}\n";
+ pr "\n";
+
+ (* display_command function, which implements guestfish -h cmd *)
+ pr "void display_command (const char *cmd)\n";
+ pr "{\n";
+ List.iter (
+ fun (name, style, _, shortdesc, longdesc) ->
+ let synopsis =
+ match style with
+ | (Err, P0) -> name
+ | (Err, args) ->
+ sprintf "%s <%s>"
+ name (
+ String.concat "> <" (
+ map_args (function
+ | String n -> n) args
+ )
+ ) in
+
+ pr " if (strcasecmp (cmd, \"%s\") == 0)\n" name;
+ pr " pod2text (\"%s - %s\", %S);\n"
+ name shortdesc
+ (" " ^ synopsis ^ "\n\n" ^ longdesc);
+ pr " else\n"
+ ) functions;
+ pr " display_builtin_command (cmd);\n";
pr "}\n";
+ pr "\n";
+
+ (* run_<action> actions *)
+ List.iter (
+ fun (name, style, _, _, _) ->
+ pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
+ pr "{\n";
+ (match style with
+ | (Err, _) -> pr " int r;\n"
+ );
+ iter_args (
+ function
+ | String name -> pr " const char *%s;\n" name
+ ) (snd style);
+
+ (* Check and convert parameters. *)
+ let argc_expected = nr_args (snd style) in
+ pr " if (argc != %d) {\n" argc_expected;
+ pr " fprintf (stderr, \"%%s should have %d parameter(s)\\n\", cmd);\n"
+ argc_expected;
+ pr " fprintf (stderr, \"type 'help %%s' for help on %%s\\n\", cmd, cmd);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ iteri_args (
+ fun i ->
+ function
+ | String name -> pr " %s = argv[%d];\n" name i
+ ) (snd style);
+
+ (* Call C API function. *)
+ pr " r = guestfs_%s " name;
+ generate_call_args ~handle:"g" style;
+ pr ";\n";
+
+ (* Check return value for errors. *)
+ (match style with
+ | (Err, _) -> pr " return r;\n"
+ );
+ pr "}\n";
+ pr "\n"
+ ) functions;
+
+ (* run_action function *)
+ pr "int run_action (const char *cmd, int argc, char *argv[])\n";
+ pr "{\n";
+ List.iter (
+ fun (name, _, _, _, _) ->
+ pr " if (strcasecmp (cmd, \"%s\") == 0)\n" name;
+ pr " return run_%s (cmd, argc, argv);\n" name;
+ pr " else\n";
+ ) functions;
+ pr " {\n";
+ pr " fprintf (stderr, \"%%s: unknown command\\n\", cmd);\n";
+ pr " return -1;\n";
+ pr " }\n";
+ pr " return 0;\n";
+ pr "}\n";
+ pr "\n"
(* Generate a C function prototype. *)
and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
generate_daemon_actions ();
close ();
+ let close = output_to "fish/cmds.c" in
+ generate_fish_cmds ();
+ close ();
+
let close = output_to "guestfs-actions.pod" in
generate_pod ();
close ()