Bring kernel version checking (utsname) into the central process.
authorRichard W.M. Jones <rjones@redhat.com>
Wed, 23 Jul 2008 15:07:24 +0000 (16:07 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Wed, 23 Jul 2008 15:07:24 +0000 (16:07 +0100)
13 files changed:
Makefile.in
dmesg/.depend
dmesg/virt_dmesg.ml
lib/.depend
lib/Makefile.in
lib/virt_mem.ml
lib/virt_mem.mli
lib/virt_mem_types.ml
lib/virt_mem_utsname.ml [new file with mode: 0644]
lib/virt_mem_utsname.mli [new file with mode: 0644]
ps/virt_ps.ml
uname/.depend
uname/virt_uname.ml

index 62e2fed..02cb91c 100644 (file)
@@ -31,6 +31,7 @@ OCAMLDOCFILES = lib/virt_mem_utils.ml \
                  lib/virt_mem_types.ml \
                  lib/virt_mem_ksyms.mli \
                  lib/virt_mem_kallsyms.mli \
+                 lib/virt_mem_utsname.mli \
                  lib/virt_mem.mli
 
 HAVE_PERLDOC    = @HAVE_PERLDOC@
index 6c94cb9..89da6ef 100644 (file)
@@ -1,4 +1,4 @@
-virt_dmesg.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_mmap.cmi \
-    ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
-virt_dmesg.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_mmap.cmx \
-    ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
+virt_dmesg.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmo \
+    ../lib/virt_mem_mmap.cmi ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
+virt_dmesg.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_types.cmx \
+    ../lib/virt_mem_mmap.cmx ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
index dd41d26..1886a92 100644 (file)
@@ -21,58 +21,56 @@ open Printf
 
 open Virt_mem_gettext.Gettext
 open Virt_mem_utils
+open Virt_mem_types
 open Virt_mem_mmap
 
-let run debug images =
-  List.iter (
-    fun (_, name, arch, mem, lookup_ksym) ->
-      try
-       (* I don't know why but this symbol doesn't exist in 2.6.9
-        * even in kallsyms.  Hence this won't work with that kernel.
-        * It's possible we can fall back to memory scanning. XXX
-        *)
-       let log_buf = lookup_ksym "log_buf" in
-       let log_buf = follow_pointer mem log_buf in
-       let log_buf_len = lookup_ksym "log_buf_len" in
-       let log_buf_len = Int64.of_int32 (get_C_int mem log_buf_len) in
-(*     let log_start = lookup_ksym "log_start" in
+let run debug (_, name, arch, mem, lookup_ksym, _) =
+  try
+    (* I don't know why but this symbol doesn't exist in 2.6.9
+     * even in kallsyms.  Hence this won't work with that kernel.
+     * It's possible we can fall back to memory scanning. XXX
+     *)
+    let log_buf = lookup_ksym "log_buf" in
+    let log_buf = follow_pointer mem log_buf in
+    let log_buf_len = lookup_ksym "log_buf_len" in
+    let log_buf_len = Int64.of_int32 (get_C_int mem log_buf_len) in
+    (* let log_start = lookup_ksym "log_start" in
        let log_start = get_C_long mem log_start in *)
-       let log_end = lookup_ksym "log_end" in
-       let log_end = get_C_long mem log_end in
-(*     let con_start = lookup_ksym "con_start" in
+    let log_end = lookup_ksym "log_end" in
+    let log_end = get_C_long mem log_end in
+    (* let con_start = lookup_ksym "con_start" in
        let con_start = get_C_long mem con_start in *)
-       let logged_chars = lookup_ksym "logged_chars" in
-       let logged_chars = get_C_long mem logged_chars in
+    let logged_chars = lookup_ksym "logged_chars" in
+    let logged_chars = get_C_long mem logged_chars in
 
-       (* This is basically the same algorithm from printk.c:do_syslog
-        * type=3, translated into OCaml.  Unlike the kernel version
-        * however we don't copy the buffer backwards.
-        *)
-       let get_log_buf idx =
-         let addr = log_buf +^ (idx &^ (log_buf_len -^ 1L)) in
-         Char.chr (get_byte mem addr)
-       in
+    (* This is basically the same algorithm from printk.c:do_syslog
+     * type=3, translated into OCaml.  Unlike the kernel version
+     * however we don't copy the buffer backwards.
+     *)
+    let get_log_buf idx =
+      let addr = log_buf +^ (idx &^ (log_buf_len -^ 1L)) in
+      Char.chr (get_byte mem addr)
+    in
 
-       let count = log_buf_len in
-       let count = if count > logged_chars then logged_chars else count in
-       let limit = log_end in
+    let count = log_buf_len in
+    let count = if count > logged_chars then logged_chars else count in
+    let limit = log_end in
 
-       let rec loop i =
-         if i >= 0L then (
-           let j = limit-^1L-^i in
-           if j +^ log_buf_len >= log_end then (
-             let c = get_log_buf j in
-             printf "%c" c;
-             loop (i-^1L)
-           )
-         )
-       in
-       loop (count-^1L)
-      with
-       Not_found ->
-         eprintf (f_"%s: could not find kernel log buffer in kernel image\n")
-           name
-  ) images
+    let rec loop i =
+      if i >= 0L then (
+       let j = limit-^1L-^i in
+       if j +^ log_buf_len >= log_end then (
+         let c = get_log_buf j in
+         printf "%c" c;
+         loop (i-^1L)
+       )
+      )
+    in
+    loop (count-^1L)
+  with
+    Not_found ->
+      eprintf (f_"%s: could not find kernel log buffer in kernel image\n")
+       name
 
 let summary = s_"display kernel messages"
 let description = s_"\
index 6eb3e7f..bb77a91 100644 (file)
@@ -2,6 +2,7 @@ virt_mem_kallsyms.cmi: virt_mem_types.cmo
 virt_mem_ksyms.cmi: virt_mem_types.cmo 
 virt_mem.cmi: virt_mem_types.cmo 
 virt_mem_mmap.cmi: virt_mem_utils.cmo 
+virt_mem_utsname.cmi: virt_mem_types.cmo 
 test_mmap.cmo: virt_mem_mmap.cmi 
 test_mmap.cmx: virt_mem_mmap.cmx 
 virt_mem_capture.cmo: virt_mem_gettext.cmo virt_mem.cmi 
@@ -16,13 +17,17 @@ virt_mem_ksyms.cmo: virt_mem_utils.cmo virt_mem_types.cmo virt_mem_mmap.cmi \
     virt_mem_gettext.cmo virt_mem_ksyms.cmi 
 virt_mem_ksyms.cmx: virt_mem_utils.cmx virt_mem_types.cmx virt_mem_mmap.cmx \
     virt_mem_gettext.cmx virt_mem_ksyms.cmi 
-virt_mem.cmo: virt_mem_version.cmo virt_mem_utils.cmo virt_mem_types.cmo \
-    virt_mem_mmap.cmi virt_mem_ksyms.cmi virt_mem_kallsyms.cmi \
-    virt_mem_gettext.cmo virt_mem.cmi 
-virt_mem.cmx: virt_mem_version.cmx virt_mem_utils.cmx virt_mem_types.cmx \
-    virt_mem_mmap.cmx virt_mem_ksyms.cmx virt_mem_kallsyms.cmx \
-    virt_mem_gettext.cmx virt_mem.cmi 
+virt_mem.cmo: virt_mem_version.cmo virt_mem_utsname.cmi virt_mem_utils.cmo \
+    virt_mem_types.cmo virt_mem_mmap.cmi virt_mem_ksyms.cmi \
+    virt_mem_kallsyms.cmi virt_mem_gettext.cmo virt_mem.cmi 
+virt_mem.cmx: virt_mem_version.cmx virt_mem_utsname.cmx virt_mem_utils.cmx \
+    virt_mem_types.cmx virt_mem_mmap.cmx virt_mem_ksyms.cmx \
+    virt_mem_kallsyms.cmx virt_mem_gettext.cmx virt_mem.cmi 
 virt_mem_mmap.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi 
 virt_mem_mmap.cmx: virt_mem_utils.cmx virt_mem_mmap.cmi 
 virt_mem_types.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi 
 virt_mem_types.cmx: virt_mem_utils.cmx virt_mem_mmap.cmx 
+virt_mem_utsname.cmo: virt_mem_utils.cmo virt_mem_types.cmo virt_mem_mmap.cmi \
+    virt_mem_gettext.cmo virt_mem_utsname.cmi 
+virt_mem_utsname.cmx: virt_mem_utils.cmx virt_mem_types.cmx virt_mem_mmap.cmx \
+    virt_mem_gettext.cmx virt_mem_utsname.cmi 
index 2edc175..9b41e68 100644 (file)
@@ -53,6 +53,7 @@ OBJS          = virt_mem_gettext.cmo \
                  virt_mem_types.cmo \
                  virt_mem_ksyms.cmo \
                  virt_mem_kallsyms.cmo \
+                 virt_mem_utsname.cmo \
                  virt_mem.cmo \
                  virt_mem_capture.cmo
 XOBJS          = $(OBJS:%.cmo=%.cmx)
index 0a956f1..03b0d1e 100644 (file)
@@ -44,11 +44,11 @@ let tools = ref []
 
 (* Registration function used by the tools. *)
 let register ?(external_cmd = true) ?(extra_args = [])
-    ?argcheck ?beforeksyms ?run
+    ?argcheck ?beforeksyms ?beforeutsname ?run
     name summary description =
   tools :=
     (name, (name, summary, description, external_cmd, extra_args,
-           argcheck, beforeksyms, run))
+           argcheck, beforeksyms, beforeutsname, run))
   :: !tools
 
 (* Main program, called from mem/virt_mem_main.ml when all the
@@ -106,7 +106,7 @@ let main () =
     match tool with
     | None ->                          (* Generic usage message. *)
        let tools = List.map (
-         fun (name, (_, summary, _, external_cmd, _, _, _, _)) ->
+         fun (name, (_, summary, _, external_cmd, _, _, _, _, _)) ->
            if external_cmd then "virt-"^name, summary
            else                 "virt-mem "^name, summary
        ) tools in
@@ -133,7 +133,7 @@ To display extra help for a single tool, do:
 Options:") tools
 
                                         (* Tool-specific usage message. *)
-    | Some (name, summary, description, external_cmd, _, _, _, _) ->
+    | Some (name, summary, description, external_cmd, _, _, _, _, _) ->
        let cmd =
          if external_cmd then "virt-" ^ name else "virt-mem " ^ name in
 
@@ -219,7 +219,7 @@ Options:") cmd summary description in
   let argspec =
     let extra_args = match tool with
       | None -> []
-      | Some (_, _, _, _, extra_args, _, _, _) -> extra_args in
+      | Some (_, _, _, _, extra_args, _, _, _, _) -> extra_args in
     let argspec = [
       "-A", Arg.String set_architecture,
         "arch " ^ s_"Set kernel architecture, endianness and word size";
@@ -270,7 +270,7 @@ Options:") cmd summary description in
    * or the user didn't give us a valid tool (eg. "virt-mem foobar").
    * Detect that final case now and give an error.
    *)
-  let name, _, _, _, _, argcheck, beforeksyms, run =
+  let name, _, _, _, _, argcheck, beforeksyms,  beforeutsname, run =
     match tool with
     | Some t -> t
     | None ->
@@ -469,16 +469,15 @@ Use 'virt-mem --help' for more help or read the manual page virt-mem(1)");
    | Some beforeksyms -> beforeksyms debug images
   );
 
-  (* If there is no run function, then there is no point continuing
-   * with the rest of the program (kernel symbol analysis) ...
+  (* If there are no more callback functions, then there is no point
+   * continuing with the rest of the program (kernel symbol analysis) ...
    *)
-  if run = None then exit 0;
+  if beforeutsname = None && run = None then exit 0;
 
   (* Do the kernel symbol analysis. *)
   let images =
     List.map (
       fun image ->
-
        (* Look for ordinary kernel symbols: *)
        let image = Virt_mem_ksyms.find_kernel_symbols debug image in
        (* Look for kallsyms: *)
@@ -506,9 +505,22 @@ Use 'virt-mem --help' for more help or read the manual page virt-mem(1)");
        image
     ) images in
 
+  (* Before utsname analysis. *)
+  (match beforeutsname with
+   | None -> ()
+   | Some beforeutsname -> List.iter (beforeutsname debug) images
+  );
+
+  (* If there are no more callback functions, then there is no point
+   * continuing with the rest of the program (kernel version analysis) ...
+   *)
+  if run = None then exit 0;
+
+  (* Get the kernel version (utsname analysis). *)
+  let images = List.map (Virt_mem_utsname.find_utsname debug) images in
+
   (* Run the tool's main function. *)
   (match run with
    | None -> ()
-   | Some run ->
-       run debug images
+   | Some run -> List.iter (run debug) images
   )
index eae488e..c807365 100644 (file)
@@ -23,7 +23,8 @@ val register :
   ?extra_args:(Arg.key * Arg.spec * Arg.doc) list ->
   ?argcheck:(bool -> unit) ->
   ?beforeksyms:(bool -> Virt_mem_types.image0 list -> unit) ->
-  ?run:(bool -> Virt_mem_types.image1 list -> unit) ->
+  ?beforeutsname:(bool -> Virt_mem_types.image1 -> unit) ->
+  ?run:(bool -> Virt_mem_types.image2 -> unit) ->
   string -> string -> Arg.usage_msg ->
   unit
   (** Tools register themselves with this call.
@@ -39,7 +40,9 @@ val register :
       on [extra_args]),
       - [?beforeksyms] called after images are loaded and before
       kernel symbols are analyzed,
-      - [?run] called after kernel symbols have been analyzed
+      - [?beforeutsname] called after kernel symbols are analyzed
+      and before the kernel version is detected
+      - [?run] called after everything
       (almost all tools supply this callback function).
 
       Pass [~external_cmd:false] if this tool doesn't have an
index 2f8b329..34f3fe7 100644 (file)
@@ -37,3 +37,21 @@ type image1 =
     * Virt_mem_utils.architecture      (* Architecture, eg. i386. *)
     * ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t (* Memory map. *)
     * (ksym -> Virt_mem_mmap.addr)     (* Kernel symbol lookup function. *)
+
+(** A kernel image, after finding kernel version (like 'uname'). *)
+type image2 =
+    int option                         (* Domain ID, if known. *)
+    * string                           (* Domain name. *)
+    * Virt_mem_utils.architecture      (* Architecture, eg. i386. *)
+    * ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t (* Memory map. *)
+    * (ksym -> Virt_mem_mmap.addr)     (* Kernel symbol lookup function. *)
+    * utsname option                   (* Kernel version, etc., if known. *)
+
+and utsname = {
+  kernel_name : string;
+  nodename : string;
+  kernel_release : string;
+  kernel_version : string;
+  machine : string;
+  domainname : string;
+}
diff --git a/lib/virt_mem_utsname.ml b/lib/virt_mem_utsname.ml
new file mode 100644 (file)
index 0000000..61a2b37
--- /dev/null
@@ -0,0 +1,93 @@
+(* Memory info command for virtual domains.
+   (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
+   http://libvirt.org/
+
+   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.
+ *)
+
+open Printf
+
+open Virt_mem_gettext.Gettext
+open Virt_mem_utils
+open Virt_mem_types
+open Virt_mem_mmap
+
+(* Truncate an OCaml string at the first ASCII NUL character, ie. as
+ * if it were a C string.
+ *)
+let truncate str =
+  try
+    let i = String.index str '\000' in
+    String.sub str 0 i
+  with
+    Not_found -> str
+
+let parse_utsname bits =
+  (* Expect the first (sysname) field to always be "Linux", which is
+   * also a good way to tell if we're synchronized to the right bit of
+   * memory.
+   *)
+  bitmatch bits with
+  | { "Linux\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" : 65*8 : string;
+      nodename : 65*8 : string;
+      release : 65*8 : string;
+      version : 65*8 : string;
+      machine : 65*8 : string;
+      domainname : 65*8 : string } ->
+      Some {
+       kernel_name = "Linux";
+       nodename = truncate nodename;
+       kernel_release = truncate release;
+       kernel_version = truncate version;
+       machine = truncate machine;
+       domainname = truncate domainname
+      }
+  | { _ } ->
+      None
+
+let find_utsname debug (domid, name, arch, mem, lookup_ksym) =
+  let utsname =
+    (* In Linux 2.6.25, the symbol is init_uts_ns.
+     * http://lxr.linux.no/linux/init/version.c
+     *)
+    try
+      let addr = lookup_ksym "init_uts_ns" in
+
+      let bs = Bitstring.bitstring_of_string (get_bytes mem addr (65*6+4)) in
+      (bitmatch bs with
+       | { _ : 32 : int;             (* the kref, atomic_t, always 32 bits *)
+          new_utsname : -1 : bitstring } ->
+          parse_utsname new_utsname
+       | { _ } ->
+          if debug then
+            eprintf (f_"%s: unexpected init_uts_ns in kernel image\n") name;
+          None
+      )
+    with
+      Not_found ->
+       (* In Linux 2.6.9, the symbol is system_utsname.
+        * http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
+        *)
+       try
+         let addr = lookup_ksym "system_utsname" in
+
+         let bits =
+           Bitstring.bitstring_of_string (get_bytes mem addr (65*6)) in
+         parse_utsname bits
+           with
+             Not_found ->
+               eprintf (f_"%s: could not find utsname in kernel image\n") name
+  in
+  (domid, name, arch, mem, lookup_ksym, utsname)
diff --git a/lib/virt_mem_utsname.mli b/lib/virt_mem_utsname.mli
new file mode 100644 (file)
index 0000000..7b62d42
--- /dev/null
@@ -0,0 +1,22 @@
+(** Get system utsname (like 'uname') from kernel. *)
+(* Memory info command for virtual domains.
+   (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
+   http://libvirt.org/
+
+   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.
+ *)
+
+val find_utsname : bool -> Virt_mem_types.image1 -> Virt_mem_types.image2
+(** Find the system utsname structure. *)
index d18ff48..df876ba 100644 (file)
@@ -222,11 +222,8 @@ let search debug mem lookup_ksym =
   let ts = loop 0 0 in
   ()
 
-let run debug images =
-  List.iter (
-    fun (domid, domname, arch, mem, lookup_ksym) ->
-      search debug mem lookup_ksym
-  ) images
+let run debug (_, _, _, mem, lookup_ksym, _) =
+  search debug mem lookup_ksym
 
 let summary = s_"list processes in virtual machine"
 let description = s_"\
index 8738997..dbdac15 100644 (file)
@@ -1,4 +1,4 @@
-virt_uname.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_mmap.cmi \
+virt_uname.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmo \
     ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
-virt_uname.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_mmap.cmx \
+virt_uname.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_types.cmx \
     ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
index 6004bb8..981f0ee 100644 (file)
@@ -21,72 +21,17 @@ open Printf
 
 open Virt_mem_gettext.Gettext
 open Virt_mem_utils
-open Virt_mem_mmap
-
-let run debug images =
-  (* Print new_utsname structure from bitstring. *)
-  let print_new_utsname name bs =
-    (* Truncate an OCaml string at the first ASCII NUL character, ie. as
-     * if it were a C string.
-     *)
-    let truncate str =
-      try
-       let i = String.index str '\000' in
-       String.sub str 0 i
-      with
-       Not_found -> str
-    in
-    (* Expect the first (sysname) field to always be "Linux", which is
-     * also a good way to tell if we're synchronized to the right bit of
-     * memory.
-     *)
-    bitmatch bs with
-    | { "Linux\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" : 65*8 : string;
-       nodename : 65*8 : string;
-       release : 65*8 : string;
-       version : 65*8 : string;
-       machine : 65*8 : string;
-       domainname : 65*8 : string } ->
-       printf "%s: Linux %s %s %s %s %s\n"
-         name
-         (truncate nodename) (truncate release)
-         (truncate version) (truncate machine) (truncate domainname)
-    | { _ } ->
-       eprintf (f_"%s: unexpected system_utsname in kernel image\n")
-         name
-  in
-
-  List.iter (
-    fun (_, name, arch, mem, lookup_ksym) ->
-      (* In Linux 2.6.25, the symbol is init_uts_ns.
-       * http://lxr.linux.no/linux/init/version.c
-       *)
-      try
-       let addr = lookup_ksym "init_uts_ns" in
-
-       let bs = Bitstring.bitstring_of_string (get_bytes mem addr (65*6+4)) in
-       (bitmatch bs with
-        | { _ : 32 : int;              (* the kref, atomic_t, always 32 bits *)
-            new_utsname : -1 : bitstring } ->
-            print_new_utsname name new_utsname
-        | { _ } ->
-            eprintf (f_"%s: unexpected init_uts_ns in kernel image\n")
-              name)
-      with
-       Not_found ->
-         (* In Linux 2.6.9, the symbol is system_utsname.
-          * http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
-          *)
-         try
-           let addr = lookup_ksym "system_utsname" in
-
-           let bs =
-             Bitstring.bitstring_of_string (get_bytes mem addr (65*6)) in
-           print_new_utsname name bs
-         with
-           Not_found ->
-             eprintf (f_"%s: could not find utsname in kernel image\n") name
-  ) images
+open Virt_mem_types
+
+let run debug (_, name, _, _, _, utsname) =
+  match utsname with
+  | Some u ->
+      printf "%s: %s %s %s %s %s %s\n"
+       name
+       u.kernel_name u.nodename u.kernel_release
+       u.kernel_version u.machine u.domainname
+  | None ->
+      eprintf (f_"%s: no system_utsname in kernel image\n") name
 
 let summary = s_"uname command for virtual machines"
 let description = s_"\