Rework status table to be less dynamically generated.
authorMarcus Brinkmann <marcus.brinkmann@ruhr-uni-bochum.de>
Tue, 14 Feb 2012 12:03:46 +0000 (13:03 +0100)
committerMarcus Brinkmann <marcus.brinkmann@ruhr-uni-bochum.de>
Tue, 14 Feb 2012 12:34:44 +0000 (13:34 +0100)
* src/Makefile.am (EXTRA_DIST): Remove mkstatus.
(BUILT_SOURCE, MOSTLYCLEANFILES): Remove.
(main_sources): Remove status-table.h, extra-stati.h.
Add status-table.c.
(status-table.h): Remove rules for built source.
* src/decrypt.c: Don't include extra-stati.h.
* src/engine-gpg.c: Don't include status-table.h.
(status_cmp): Remove function.
(read_status): Use _gpgme_parse_status.
* src/engine-gpgsm.c: Don't include status-table.h.
(status_cmp, parse_status): Remove function.
(gpgsm_assuan_simple_command, status_handler): Use _gpgme_parse_status.
* src/engine-uiserver.c: Don't include status-table.h.
(status_cmp, parse_status): Remove function.
(uiserver_assuan_simple_command, status_handler): Use
_gpgme_parse_status.
* src/gpgme.h.in (gpgme_status_code_t): Add
GPGME_STATUS_DECRYPTION_INFO.
* src/util.h (_gpgme_status_init,_gpgme_parse_status): New declaration.
* src/status-table.c: New file.
* src/extra-stati.h, src/mkstatus: Files removed.
* version.c (do_subsystem_inits): Call _gpgme_status_init.

src/Makefile.am
src/decrypt.c
src/engine-gpg.c
src/engine-gpgsm.c
src/engine-uiserver.c
src/extra-stati.h [deleted file]
src/gpgme.h.in
src/mkstatus [deleted file]
src/status-table.c [new file with mode: 0644]
src/util.h
src/version.c

index e456d80..ea8e70e 100644 (file)
 ## Process this file with automake to produce Makefile.in
 
 # Note: moc_kdpipeiodevice should actually be a dependcy below.
-EXTRA_DIST = gpgme-config.in gpgme.m4 mkstatus libgpgme.vers ChangeLog-2011 \
+EXTRA_DIST = gpgme-config.in gpgme.m4 libgpgme.vers ChangeLog-2011 \
             gpgme.h.in versioninfo.rc.in gpgme.def moc_kdpipeiodevice.cpp
 
-BUILT_SOURCES = status-table.h
-MOSTLYCLEANFILES = status-table.h
 bin_SCRIPTS = gpgme-config
 m4datadir = $(datadir)/aclocal
 m4data_DATA = gpgme.m4
@@ -115,8 +113,7 @@ main_sources =                                                              \
        key.c keylist.c trust-item.c trustlist.c                        \
        import.c export.c genkey.c delete.c edit.c getauditlog.c        \
        opassuan.c passwd.c                                             \
-       engine.h engine-backend.h engine.c engine-gpg.c status-table.h  \
-       extra-stati.h                                                   \
+       engine.h engine-backend.h engine.c engine-gpg.c status-table.c  \
        $(gpgsm_components) $(assuan_components) $(gpgconf_components)  \
        $(uiserver_components)                                          \
        $(g13_components) vfs-mount.c vfs-create.c                      \
@@ -228,10 +225,6 @@ endif
 noinst_PROGRAMS = gpgme-tool
 gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@
 
-status-table.h : gpgme.h extra-stati.h
-       cat $(builddir)/gpgme.h $(srcdir)extra-stati.h \
-          | $(srcdir)/mkstatus  > status-table.h
-
 install-data-local: install-def-file
 
 uninstall-local: uninstall-def-file
index b74c508..43945ec 100644 (file)
@@ -31,7 +31,6 @@
 #include "util.h"
 #include "context.h"
 #include "ops.h"
-#include "extra-stati.h"
 
 
 \f
index f163f0f..cbb456e 100644 (file)
@@ -1,7 +1,7 @@
 /* engine-gpg.c - Gpg Engine.
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-                 2009, 2010 g10 Code GmbH
+                 2009, 2010, 2012 g10 Code GmbH
  
    This file is part of GPGME.
  
@@ -43,7 +43,6 @@
 #include "sema.h"
 #include "debug.h"
 
-#include "status-table.h"
 #include "engine-backend.h"
 
 
@@ -965,16 +964,6 @@ add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
 }
 
 
-static int
-status_cmp (const void *ap, const void *bp)
-{
-  const struct status_table_s *a = ap;
-  const struct status_table_s *b = bp;
-
-  return strcmp (a->name, b->name);
-}
-
-
 /* Handle the status output of GnuPG.  This function does read entire
    lines and passes them as C strings to the callback function (we can
    use C Strings because the status output is always UTF-8 encoded).
@@ -1032,8 +1021,8 @@ read_status (engine_gpg_t gpg)
              if (!strncmp (buffer, "[GNUPG:] ", 9)
                  && buffer[9] >= 'A' && buffer[9] <= 'Z')
                {
-                 struct status_table_s t, *r;
                  char *rest;
+                 gpgme_status_code_t r;
 
                  rest = strchr (buffer + 9, ' ');
                  if (!rest)
@@ -1041,18 +1030,15 @@ read_status (engine_gpg_t gpg)
                  else
                    *rest++ = 0;
                     
-                 t.name = buffer+9;
-                 /* (the status table has one extra element) */
-                 r = bsearch (&t, status_table, DIM(status_table) - 1,
-                              sizeof t, status_cmp);
-                 if (r)
+                 r = _gpgme_parse_status (buffer + 9);
+                 if (r >= 0)
                    {
                      if (gpg->cmd.used
-                         && (r->code == GPGME_STATUS_GET_BOOL
-                             || r->code == GPGME_STATUS_GET_LINE
-                             || r->code == GPGME_STATUS_GET_HIDDEN))
+                         && (r == GPGME_STATUS_GET_BOOL
+                             || r == GPGME_STATUS_GET_LINE
+                             || r == GPGME_STATUS_GET_HIDDEN))
                        {
-                         gpg->cmd.code = r->code;
+                         gpg->cmd.code = r;
                          if (gpg->cmd.keyword)
                            free (gpg->cmd.keyword);
                          gpg->cmd.keyword = strdup (rest);
@@ -1075,12 +1061,12 @@ read_status (engine_gpg_t gpg)
                        {
                          gpgme_error_t err;
                          err = gpg->status.fnc (gpg->status.fnc_value, 
-                                                r->code, rest);
+                                                r, rest);
                          if (err)
                            return err;
                         }
                     
-                     if (r->code == GPGME_STATUS_END_STREAM)
+                     if (r == GPGME_STATUS_END_STREAM)
                        {
                          if (gpg->cmd.used)
                            {
index 4b7b5a2..0620458 100644 (file)
@@ -48,7 +48,6 @@
 #include "data.h"
 
 #include "assuan.h"
-#include "status-table.h"
 #include "debug.h"
 
 #include "engine-backend.h"
@@ -559,9 +558,6 @@ gpgsm_set_locale (void *engine, int category, const char *value)
 }
 
 
-/* Forward declaration.  */
-static gpgme_status_code_t parse_status (const char *name);
-
 static gpgme_error_t
 gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
                             engine_status_handler_t status_fnc,
@@ -604,7 +600,7 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0 && status_fnc)
            err = status_fnc (status_fnc_value, r, rest);
@@ -756,27 +752,6 @@ map_data_enc (gpgme_data_t d)
 }
 
 
-static int
-status_cmp (const void *ap, const void *bp)
-{
-  const struct status_table_s *a = ap;
-  const struct status_table_s *b = bp;
-
-  return strcmp (a->name, b->name);
-}
-
-
-static gpgme_status_code_t
-parse_status (const char *name)
-{
-  struct status_table_s t, *r;
-  t.name = name;
-  r = bsearch (&t, status_table, DIM(status_table) - 1,
-              sizeof t, status_cmp);
-  return r ? r->code : -1;
-}
-
-
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
@@ -963,7 +938,7 @@ status_handler (void *opaque, int fd)
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0)
            {
index 92f7536..c705a4b 100644 (file)
@@ -453,9 +453,6 @@ uiserver_set_protocol (void *engine, gpgme_protocol_t protocol)
 }
 
 
-/* Forward declaration.  */
-static gpgme_status_code_t parse_status (const char *name);
-
 static gpgme_error_t
 uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
                             engine_status_handler_t status_fnc,
@@ -498,7 +495,7 @@ uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0 && status_fnc)
            err = status_fnc (status_fnc_value, r, rest);
@@ -620,27 +617,6 @@ map_data_enc (gpgme_data_t d)
 }
 
 
-static int
-status_cmp (const void *ap, const void *bp)
-{
-  const struct status_table_s *a = ap;
-  const struct status_table_s *b = bp;
-
-  return strcmp (a->name, b->name);
-}
-
-
-static gpgme_status_code_t
-parse_status (const char *name)
-{
-  struct status_table_s t, *r;
-  t.name = name;
-  r = bsearch (&t, status_table, DIM(status_table) - 1,
-              sizeof t, status_cmp);
-  return r ? r->code : -1;
-}
-
-
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
@@ -827,7 +803,7 @@ status_handler (void *opaque, int fd)
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0)
            {
diff --git a/src/extra-stati.h b/src/extra-stati.h
deleted file mode 100644 (file)
index 59cccf9..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* extra-stati.lst - Extra GnuPG status codes.
-   Copyright 2011 g10 Code GmbH
-
-   This file is free software; as a special exception the author gives
-   unlimited permission to copy and/or distribute it, with or without
-   modifications, as long as this notice is preserved.
-
-   This file is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
-   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-   PURPOSE.  */
-
-/* A list of internal status code to be processed by mkstatus.  Those
- * status codes are not part of the API but internally required by
- * gpgme.  We use a second enum type here but make sure that the
- * values don't clash with those of gpgme_status_code_t.
- */
-
-enum
-  {
-    /* This value is the first used one.  It needs to be larger than
-       the last value of gpgme_status_code_t.  There is no need to
-       explictly list the values because they are internal only.  */
-    _GPGME_STATUS_FIRST_EXTRA = 192,
-
-    GPGME_STATUS_DECRYPTION_INFO,
-
-    _GPGME_STATUS_LAST_EXTRA
-  };
index e75de19..dad8d94 100644 (file)
@@ -499,11 +499,11 @@ typedef enum
     GPGME_STATUS_BACKUP_KEY_CREATED = 78,
     GPGME_STATUS_PKA_TRUST_BAD = 79,
     GPGME_STATUS_PKA_TRUST_GOOD = 80,
-
     GPGME_STATUS_PLAINTEXT = 81,
     GPGME_STATUS_INV_SGNR = 82,
     GPGME_STATUS_NO_SGNR = 83,
-    GPGME_STATUS_SUCCESS = 84
+    GPGME_STATUS_SUCCESS = 84,
+    GPGME_STATUS_DECRYPTION_INFO = 85
   }
 gpgme_status_code_t;
 
diff --git a/src/mkstatus b/src/mkstatus
deleted file mode 100755 (executable)
index 3fbfbf9..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-# mkstatus - Extract error strings from rungpg.h
-#            and create a lookup table
-#      Copyright (C) 2000 Werner Koch (dd9jn)
-#       Copyright (C) 2001 g10 Code GmbH
-#
-# This file is part of GPGME.
-#
-# GPGME is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as
-# published by the Free Software Foundation; either version 2.1 of the
-# License, or (at your option) any later version.
-#
-# GPGME 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 Lesser General
-# Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-# resetting collate is important, so that the bsearch works properly
-LC_ALL=C
-LC_COLLATE=C
-export LC_ALL LC_COLLATE
-
-cat <<EOF
-/* Generated automatically by mkstatus */
-/* Do not edit! */
-
-struct status_table_s {
-    const char *name;
-    gpgme_status_code_t code;
-};
-
-static struct status_table_s status_table[] =
-{
-EOF
-
-awk '
-okay == 0 && /GPGME_STATUS_ENTER/        { okay = 1 }
-okay == 2 && /_GPGME_STATUS_FIRST_EXTRA/ { okay = 1; next }
-okay != 1                                { next }
-/}/                                      { okay = 2 }
-/_GPGME_STATUS_LAST_EXTRA/               { exit 0 }
-/GPGME_STATUS_[A-Za-z_]*/ { sub (/,/, "", $1); printf "  { \"%s\", %s },\n", substr($1,14), $1 }
-' | sort
-
-cat <<EOF
-  {NULL, 0}
-};
-
-EOF
diff --git a/src/status-table.c b/src/status-table.c
new file mode 100644 (file)
index 0000000..276f70e
--- /dev/null
@@ -0,0 +1,156 @@
+/* gpgme.c - GnuPG Made Easy.
+   Copyright (C) 2000 Werner Koch (dd9jn)
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2012 g10 Code GmbH
+
+   This file is part of GPGME.
+
+   GPGME is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   GPGME 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "util.h"
+
+struct status_table_s {
+    const char *name;
+    gpgme_status_code_t code;
+};
+
+
+/* Lexicographically sorted ('_' comes after any letter).  You can use
+   the Emacs command M-x sort-lines.  But don't sweat it, the table is
+   sorted at start up, too.  */
+static struct status_table_s status_table[] =
+{
+  { "ALREADY_SIGNED", GPGME_STATUS_ALREADY_SIGNED },
+  { "BACKUP_KEY_CREATED", GPGME_STATUS_BACKUP_KEY_CREATED },
+  { "BADARMOR", GPGME_STATUS_BADARMOR },
+  { "BADMDC", GPGME_STATUS_BADMDC },
+  { "BADSIG", GPGME_STATUS_BADSIG },
+  { "BAD_PASSPHRASE", GPGME_STATUS_BAD_PASSPHRASE },
+  { "BEGIN_DECRYPTION", GPGME_STATUS_BEGIN_DECRYPTION },
+  { "BEGIN_ENCRYPTION", GPGME_STATUS_BEGIN_ENCRYPTION },
+  { "BEGIN_STREAM", GPGME_STATUS_BEGIN_STREAM },
+  { "CARDCTRL", GPGME_STATUS_CARDCTRL },
+  { "DECRYPTION_FAILED", GPGME_STATUS_DECRYPTION_FAILED },
+  { "DECRYPTION_OKAY", GPGME_STATUS_DECRYPTION_OKAY },
+  { "DELETE_PROBLEM", GPGME_STATUS_DELETE_PROBLEM },
+  { "ENC_TO", GPGME_STATUS_ENC_TO },
+  { "END_DECRYPTION", GPGME_STATUS_END_DECRYPTION },
+  { "END_ENCRYPTION", GPGME_STATUS_END_ENCRYPTION },
+  { "END_STREAM", GPGME_STATUS_END_STREAM },
+  { "ENTER", GPGME_STATUS_ENTER },
+  { "ERRMDC", GPGME_STATUS_ERRMDC },
+  { "ERROR", GPGME_STATUS_ERROR },
+  { "ERRSIG", GPGME_STATUS_ERRSIG },
+  { "EXPKEYSIG", GPGME_STATUS_EXPKEYSIG },
+  { "EXPSIG", GPGME_STATUS_EXPSIG },
+  { "FILE_DONE", GPGME_STATUS_FILE_DONE },
+  { "FILE_ERROR", GPGME_STATUS_FILE_ERROR },
+  { "FILE_START", GPGME_STATUS_FILE_START },
+  { "GET_BOOL", GPGME_STATUS_GET_BOOL },
+  { "GET_HIDDEN", GPGME_STATUS_GET_HIDDEN },
+  { "GET_LINE", GPGME_STATUS_GET_LINE },
+  { "GOODMDC", GPGME_STATUS_GOODMDC },
+  { "GOODSIG", GPGME_STATUS_GOODSIG },
+  { "GOOD_PASSPHRASE", GPGME_STATUS_GOOD_PASSPHRASE },
+  { "GOT_IT", GPGME_STATUS_GOT_IT },
+  { "IMPORTED", GPGME_STATUS_IMPORTED },
+  { "IMPORT_OK", GPGME_STATUS_IMPORT_OK },
+  { "IMPORT_PROBLEM", GPGME_STATUS_IMPORT_PROBLEM },
+  { "IMPORT_RES", GPGME_STATUS_IMPORT_RES },
+  { "INV_RECP", GPGME_STATUS_INV_RECP },
+  { "INV_SGNR", GPGME_STATUS_INV_SGNR },
+  { "KEYEXPIRED", GPGME_STATUS_KEYEXPIRED },
+  { "KEYREVOKED", GPGME_STATUS_KEYREVOKED },
+  { "KEY_CREATED", GPGME_STATUS_KEY_CREATED },
+  { "LEAVE", GPGME_STATUS_LEAVE },
+  { "MISSING_PASSPHRASE", GPGME_STATUS_MISSING_PASSPHRASE },
+  { "NEED_PASSPHRASE", GPGME_STATUS_NEED_PASSPHRASE },
+  { "NEED_PASSPHRASE_PIN", GPGME_STATUS_NEED_PASSPHRASE_PIN },
+  { "NEED_PASSPHRASE_SYM", GPGME_STATUS_NEED_PASSPHRASE_SYM },
+  { "NEWSIG", GPGME_STATUS_NEWSIG },
+  { "NODATA", GPGME_STATUS_NODATA },
+  { "NOTATION_DATA", GPGME_STATUS_NOTATION_DATA },
+  { "NOTATION_NAME", GPGME_STATUS_NOTATION_NAME },
+  { "NO_PUBKEY", GPGME_STATUS_NO_PUBKEY },
+  { "NO_RECP", GPGME_STATUS_NO_RECP },
+  { "NO_SECKEY", GPGME_STATUS_NO_SECKEY },
+  { "NO_SGNR", GPGME_STATUS_NO_SGNR },
+  { "PKA_TRUST_BAD", GPGME_STATUS_PKA_TRUST_BAD },
+  { "PKA_TRUST_GOOD", GPGME_STATUS_PKA_TRUST_GOOD },
+  { "PLAINTEXT", GPGME_STATUS_PLAINTEXT },
+  { "POLICY_URL", GPGME_STATUS_POLICY_URL },
+  { "PROGRESS", GPGME_STATUS_PROGRESS },
+  { "REVKEYSIG", GPGME_STATUS_REVKEYSIG },
+  { "RSA_OR_IDEA", GPGME_STATUS_RSA_OR_IDEA },
+  { "SC_OP_FAILURE", GPGME_STATUS_SC_OP_FAILURE },
+  { "SC_OP_SUCCESS", GPGME_STATUS_SC_OP_SUCCESS },
+  { "SESSION_KEY", GPGME_STATUS_SESSION_KEY },
+  { "SHM_GET", GPGME_STATUS_SHM_GET },
+  { "SHM_GET_BOOL", GPGME_STATUS_SHM_GET_BOOL },
+  { "SHM_GET_HIDDEN", GPGME_STATUS_SHM_GET_HIDDEN },
+  { "SHM_INFO", GPGME_STATUS_SHM_INFO },
+  { "SIGEXPIRED", GPGME_STATUS_SIGEXPIRED },
+  { "SIG_CREATED", GPGME_STATUS_SIG_CREATED },
+  { "SIG_ID", GPGME_STATUS_SIG_ID },
+  { "SIG_SUBPACKET", GPGME_STATUS_SIG_SUBPACKET },
+  { "SUCCESS", GPGME_STATUS_SUCCESS },
+  { "TRUNCATED", GPGME_STATUS_TRUNCATED },
+  { "TRUST_FULLY", GPGME_STATUS_TRUST_FULLY },
+  { "TRUST_MARGINAL", GPGME_STATUS_TRUST_MARGINAL },
+  { "TRUST_NEVER", GPGME_STATUS_TRUST_NEVER },
+  { "TRUST_ULTIMATE", GPGME_STATUS_TRUST_ULTIMATE },
+  { "TRUST_UNDEFINED", GPGME_STATUS_TRUST_UNDEFINED },
+  { "UNEXPECTED", GPGME_STATUS_UNEXPECTED },
+  { "USERID_HINT", GPGME_STATUS_USERID_HINT },
+  { "VALIDSIG", GPGME_STATUS_VALIDSIG },
+  { "ABORT", GPGME_STATUS_ABORT },
+  {NULL, 0}
+};
+
+
+static int
+status_cmp (const void *ap, const void *bp)
+{
+  const struct status_table_s *a = ap;
+  const struct status_table_s *b = bp;
+
+  return strcmp (a->name, b->name);
+}
+
+
+void
+_gpgme_status_init (void)
+{
+  qsort (status_table,
+        DIM(status_table) - 1, sizeof (status_table[0]),
+        status_cmp);
+}
+
+
+gpgme_status_code_t
+_gpgme_parse_status (const char *name)
+{
+  struct status_table_s t, *r;
+  t.name = name;
+  r = bsearch (&t, status_table, DIM(status_table) - 1,
+              sizeof t, status_cmp);
+  return r ? r->code : -1;
+}
index 27620aa..cf18099 100644 (file)
@@ -137,6 +137,12 @@ gpgme_error_t _gpgme_map_gnupg_error (char *err);
 gpgme_error_t _gpgme_getenv (const char *name, char **value);
 
 \f
+/*-- status-table.c --*/
+/* Convert a status string to a status code.  */
+void _gpgme_status_init (void);
+gpgme_status_code_t _gpgme_parse_status (const char *name);
+
+\f
 #ifdef HAVE_W32_SYSTEM
 int _gpgme_mkstemp (int *fd, char **name);
 const char *_gpgme_get_w32spawn_path (void);
index e02037e..3aef404 100644 (file)
@@ -35,8 +35,9 @@
 #include "debug.h"
 #include "context.h"
 
-/* For _gpgme_sema_subsystem_init ().  */
+/* For _gpgme_sema_subsystem_init and _gpgme_status_init.  */
 #include "sema.h"
+#include "util.h"
 
 #ifdef HAVE_ASSUAN_H
 #include "assuan.h"
@@ -76,6 +77,7 @@ do_subsystem_inits (void)
   _gpgme_sema_subsystem_init ();
   _gpgme_debug_subsystem_init ();
   _gpgme_io_subsystem_init ();
+  _gpgme_status_init ();
 
   done = 1;
 }