}
 }
 
+/*
+ * Possible status values:
+ * - 0: no error yet
+ * - >0: errno value
+ * - EOF: end of file (remote end closed connection; not necessarily an error)
+ */
 int
 jsonrpc_get_status(const struct jsonrpc *rpc)
 {
 
         ovsdb_error_destroy(error);
     }
 }
-
 
     struct pcap_hdr ph;
     if (fread(&ph, sizeof ph, 1, file) != 1) {
         int error = ferror(file) ? errno : EOF;
-        VLOG_WARN("failed to read pcap header: %s",
-                  error > 0 ? strerror(error) : "end of file");
+        VLOG_WARN("failed to read pcap header: %s", ovs_retval_to_string(error));
         return error;
     }
     if (ph.magic_number != 0xa1b2c3d4 && ph.magic_number != 0xd4c3b2a1) {
     if (fread(&prh, sizeof prh, 1, file) != 1) {
         int error = ferror(file) ? errno : EOF;
         VLOG_WARN("failed to read pcap record header: %s",
-                  error > 0 ? strerror(error) : "end of file");
+                  ovs_retval_to_string(error));
         return error;
     }
 
     if (fread(data, len, 1, file) != 1) {
         int error = ferror(file) ? errno : EOF;
         VLOG_WARN("failed to read pcap packet: %s",
-                  error > 0 ? strerror(error) : "end of file");
+                  ovs_retval_to_string(error));
         ofpbuf_delete(buf);
         return error;
     }
 
     vfprintf(stderr, format, args);
     va_end(args);
     if (err_no != 0)
-        fprintf(stderr, " (%s)",
-                err_no == EOF ? "end of file" : strerror(err_no));
+        fprintf(stderr, " (%s)", ovs_retval_to_string(err_no));
     putc('\n', stderr);
 
     exit(EXIT_FAILURE);
     vfprintf(stderr, format, args);
     va_end(args);
     if (err_no != 0) {
-        fprintf(stderr, " (%s)",
-                err_no == EOF ? "end of file" : strerror(err_no));
+        fprintf(stderr, " (%s)", ovs_retval_to_string(err_no));
     }
     putc('\n', stderr);
 
     errno = save_errno;
 }
 
+/* Many OVS functions return an int which is one of:
+ * - 0: no error yet
+ * - >0: errno value
+ * - EOF: end of file (not necessarily an error; depends on the function called)
+ *
+ * Returns the appropriate human-readable string. The caller must copy the
+ * string if it wants to hold onto it, as the storage may be overwritten on
+ * subsequent function calls.
+ */
+const char *
+ovs_retval_to_string(int retval)
+{
+    static char unknown[48];
+
+    if (!retval) {
+        return "";
+    }
+    if (retval > 0) {
+        return strerror(retval);
+    }
+    if (retval == EOF) {
+        return "End of file";
+    }
+    snprintf(unknown, sizeof unknown, "***unknown return value: %d***", retval);
+    return unknown;
+}
+
 /* Sets program_name based on 'argv0'.  Should be called at the beginning of
  * main(), as "set_program_name(argv[0]);".  */
 void set_program_name(const char *argv0)
 
 void ovs_fatal(int err_no, const char *format, ...)
     PRINTF_FORMAT(2, 3) NO_RETURN;
 void ovs_error(int err_no, const char *format, ...) PRINTF_FORMAT(2, 3);
+const char *ovs_retval_to_string(int);
 void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii);
 
 bool str_to_int(const char *, int base, int *);
 
 
         cinfo->pairs.n = 0;
 
-        if (last_error == EOF) {
-            cinfo->pairs.keys[cinfo->pairs.n] = "last_error";
-            cinfo->pairs.values[cinfo->pairs.n++] = xstrdup("End of file");
-        } else if (last_error > 0) {
+        if (last_error) {
             cinfo->pairs.keys[cinfo->pairs.n] = "last_error";
             cinfo->pairs.values[cinfo->pairs.n++] =
-                xstrdup(strerror(last_error));
+                xstrdup(ovs_retval_to_string(last_error));
         }
 
         cinfo->pairs.keys[cinfo->pairs.n] = "state";