More tidy up of messages.
[libguestfs.git] / src / generator.ml
index a54ac3f..fbb4a40 100755 (executable)
@@ -42,7 +42,7 @@ and argt =
 
 let functions = [
   ("mount", (Err, P2 (String "device", String "mountpoint")), 1,
 
 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
    "\
 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
@@ -53,10 +53,16 @@ names can be used.
 The rules are the same as for L<mount(2)>:  A filesystem must
 first be mounted on C</> before others can be mounted.  Other
 filesystems can only be mounted on directories which already
 The rules are the same as for L<mount(2)>:  A filesystem must
 first be mounted on C</> before others can be mounted.  Other
 filesystems can only be mounted on directories which already
-exist.");
+exist.
+
+The mounted filesystem is writable, if we have sufficient permissions
+on the underlying device.
+
+The filesystem options C<sync> and C<noatime> are set with this
+call, in order to improve reliability.");
 
   ("sync", (Err, P0), 2,
 
   ("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.
    "\
 This syncs the disk, so that any writes are flushed through to the
 underlying disk image.
@@ -65,10 +71,10 @@ You should always call this if you have modified a disk image, before
 calling C<guestfs_close>.");
 
   ("touch", (Err, P1 (String "path")), 3,
 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
    "\
 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.");
 ]
 
 to create a new zero-length file.");
 ]
 
@@ -81,6 +87,11 @@ let iter_args f = function
   | P1 arg1 -> f arg1
   | P2 (arg1, arg2) -> f arg1; f arg2
 
   | P1 arg1 -> f arg1
   | P2 (arg1, arg2) -> f arg1; f arg2
 
+let map_args f = function
+  | P0 -> []
+  | P1 arg1 -> [f arg1]
+  | P2 (arg1, arg2) -> [f arg1; f arg2]
+
 type comment_style = CStyle | HashStyle | OCamlStyle
 type license = GPLv2 | LGPLv2
 
 type comment_style = CStyle | HashStyle | OCamlStyle
 type license = GPLv2 | LGPLv2
 
@@ -312,7 +323,6 @@ and generate_client_actions () =
           pr "  serial = dispatch (g, GUESTFS_PROC_%s, NULL, NULL);\n"
             (String.uppercase shortname)
        | (_, args) ->
           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
           iter_args (
             function
             | String name -> pr "  args.%s = (char *) %s;\n" name name
@@ -441,7 +451,75 @@ and generate_daemon_actions () =
   pr "    default:\n";
   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
   pr "  }\n";
   pr "    default:\n";
   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
   pr "  }\n";
+  pr "}\n"
+
+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";
+  pr "\n";
+
+  (* run_action function *)
+  pr "int run_action (const char *cmd, int argc, char *argv[])\n";
+  pr "{\n";
+  List.iter (
+    fun (name, style, _, _, _) ->
+      pr "  if (strcasecmp (cmd, \"%s\") == 0)\n" name;
+      pr "    printf (\"running %s ...\\n\");\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 a C function prototype. *)
 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
@@ -522,6 +600,10 @@ let () =
   generate_daemon_actions ();
   close ();
 
   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 ()
   let close = output_to "guestfs-actions.pod" in
   generate_pod ();
   close ()