GNUPG-1-9-BRANCH gnupg/tools (ChangeLog Makefile.am symcryptrun.c)

cvs user marcus cvs at cvs.gnupg.org
Mon Apr 11 00:54:55 CEST 2005


    Date: Monday, April 11, 2005 @ 01:10:52
  Author: marcus
    Path: /cvs/gnupg/gnupg/tools
     Tag: GNUPG-1-9-BRANCH

   Added: symcryptrun.c
Modified: ChangeLog Makefile.am

2005-04-11  Marcus Brinkmann  <marcus at g10code.de>

	* Makefile.am (bin_PROGRAMS): Add symcryptrun.
	(symcryptrun_SOURCES, symcryptrun_LDADD): New variables.
	* symcryptrun.c: New file.


---------------+
 ChangeLog     |    6 
 Makefile.am   |    7 
 symcryptrun.c |  848 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 860 insertions(+), 1 deletion(-)


Index: gnupg/tools/ChangeLog
diff -u gnupg/tools/ChangeLog:1.25.2.64 gnupg/tools/ChangeLog:1.25.2.65
--- gnupg/tools/ChangeLog:1.25.2.64	Wed Mar  9 11:11:14 2005
+++ gnupg/tools/ChangeLog	Mon Apr 11 01:10:52 2005
@@ -1,3 +1,9 @@
+2005-04-11  Marcus Brinkmann  <marcus at g10code.de>
+
+	* Makefile.am (bin_PROGRAMS): Add symcryptrun.
+	(symcryptrun_SOURCES, symcryptrun_LDADD): New variables.
+	* symcryptrun.c: New file.
+
 2005-03-09  Werner Koch  <wk at g10code.com>
 
 	* gpgconf-comp.c <dirmngr>: Add honor-http-proxy.
Index: gnupg/tools/Makefile.am
diff -u gnupg/tools/Makefile.am:1.31.2.12 gnupg/tools/Makefile.am:1.31.2.13
--- gnupg/tools/Makefile.am:1.31.2.12	Thu Feb 24 18:36:11 2005
+++ gnupg/tools/Makefile.am	Mon Apr 11 01:10:52 2005
@@ -30,7 +30,7 @@
 
 bin_SCRIPTS = gpgsm-gencert.sh
 
-bin_PROGRAMS = gpgconf gpg-connect-agent
+bin_PROGRAMS = gpgconf gpg-connect-agent symcryptrun
 if !HAVE_W32_SYSTEM
 bin_PROGRAMS += watchgnupg
 endif
@@ -39,6 +39,11 @@
 
 gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @LIBINTL@
 
+symcryptrun_SOURCES = symcryptrun.c
+symcryptrun_LDADD = -lutil ../jnlib/libjnlib.a ../common/libcommon.a \
+		    ../common/libsimple-pwquery.a $(LIBGCRYPT_LIBS) \
+		    $(GPG_ERROR_LIBS) $(LIBINTL)
+
 watchgnupg_SOURCES = watchgnupg.c 
 
 gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c
Index: gnupg/tools/symcryptrun.c
diff -u /dev/null gnupg/tools/symcryptrun.c:1.1.2.1
--- /dev/null	Mon Apr 11 01:10:52 2005
+++ gnupg/tools/symcryptrun.c	Mon Apr 11 01:10:52 2005
@@ -0,0 +1,848 @@
+/* symcryptrun.c - Tool to call simple symmetric encryption tools.
+ *	Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* Sometimes simple encryption tools are already in use for a long
+   time and there is a desire to integrate them into the GnuPG
+   framework.  The protocols and encryption methods might be
+   non-standard or not even properly documented, so that a
+   full-fledged encryption tool with an interface like gpg is not
+   doable.  This simple wrapper program provides a solution: It
+   operates by calling the encryption/decryption module and providing
+   the passphrase for a key (or even the key directly) using the
+   standard pinentry mechanism through gpg-agent.  */
+
+/* This program is invoked in the following way:
+
+   symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE \
+     [--decrypt | --encrypt]
+
+   For encryption, the plain text must be provided on STDIN, and the
+   ciphertext will be output to STDOUT.  For decryption vice versa.
+
+   CLASS can currently only be "confucius".
+
+   PROGRAM must be the path to the crypto engine.
+
+   KEYFILE must contain the secret key, which may be protected by a
+   passphrase.  The passphrase is retrieved via the pinentry program.
+
+
+   The GPG Agent _must_ be running before starting symcryptrun.
+
+   The possible exit status codes:
+
+   0	Success
+   1	Some error occured
+   2	No valid passphrase was provided
+   3	The operation was canceled by the user
+
+   Other classes may be added in the future.  */
+
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pty.h>
+#include <utmp.h>
+#include <ctype.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+#include <gpg-error.h>
+
+#define JNLIB_NEED_LOG_LOGV
+#include "i18n.h"
+#include "../common/util.h"
+
+/* FIXME: Bah.  For spwq_secure_free.  */
+#define SIMPLE_PWQUERY_IMPLEMENTATION 1
+#include "../common/simple-pwquery.h"
+
+
+/* Used by gcry for logging */
+static void
+my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
+{
+  /* translate the log levels */
+  switch (level)
+    {
+    case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
+    case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
+    case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
+    case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
+    case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
+    case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
+    case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
+    default:            level = JNLIB_LOG_ERROR; break;      }
+  log_logv (level, fmt, arg_ptr);
+}
+
+
+/* Constants to identify the commands and options. */
+enum cmd_and_opt_values
+  {
+    aNull = 0,
+    oQuiet      = 'q',
+    oVerbose	= 'v',
+
+    oNoVerbose	= 500,
+    oLogFile,
+    oHomedir,
+    oClass,
+    oProgram,
+    oKeyfile,
+    oDecrypt,
+    oEncrypt,
+  };
+
+
+/* The list of commands and options.  */
+static ARGPARSE_OPTS opts[] =
+  {
+    { 301, NULL, 0, N_("@\nCommands:\n ") },
+
+    { oDecrypt, "decrypt", 0, N_("decryption modus")},
+    { oEncrypt, "encrypt", 0, N_("encryption modus")},
+    
+    { 302, NULL, 0, N_("@\nOptions:\n ") },
+    
+    { oClass, "class", 2, N_("tool class (confucius)")},
+    { oProgram, "program", 2, N_("program filename")},
+
+    { oKeyfile, "keyfile", 2, N_("secret key file (required)")},
+
+    { oVerbose, "verbose",  0, N_("verbose") },
+    { oQuiet, "quiet",      0, N_("quiet") },
+    { oLogFile, "log-file", 2, N_("use a log file for the server")},
+
+    /* Hidden options.  */
+    { oNoVerbose, "no-verbose",  0, "@"},
+    { oHomedir, "homedir", 2, "@" },   
+
+    {0}
+  };
+
+
+/* We keep all global options in the structure OPT.  */
+struct
+{
+  int verbose;		/* Verbosity level.  */
+  int quiet;		/* Be extra quiet.  */
+  const char *homedir;  /* Configuration directory name */
+
+  char *class;
+  char *program;
+  char *keyfile;
+} opt;
+
+
+/* Print usage information and and provide strings for help.  */
+static const char *
+my_strusage (int level)
+{
+  const char *p;
+
+  switch (level)
+    {
+    case 11: p = "symcryptrun (GnuPG)";
+      break;
+    case 13: p = VERSION; break;
+    case 17: p = PRINTABLE_OS_NAME; break;
+    case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
+      break;
+    case 1:
+    case 40: p = _("Usage: symcryptrun [options] (-h for help)");
+      break;
+    case 41:
+      p = _("Syntax: symcryptrun --class CLASS --program PROGRAM "
+	    "--keyfile KEYFILE [options...] COMMAND\n"
+            "Call a simple symmetric encryption tool\n");
+      break;
+    case 31: p = "\nHome: "; break;
+    case 32: p = opt.homedir; break;
+    case 33: p = "\n"; break;
+
+    default: p = NULL; break;
+    }
+  return p;
+}
+
+
+/* Initialize the gettext system.  */
+static void
+i18n_init(void)
+{
+#ifdef USE_SIMPLE_GETTEXT
+  set_gettext_file (PACKAGE_GT);
+#else
+# ifdef ENABLE_NLS
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE_GT, LOCALEDIR);
+  textdomain (PACKAGE_GT);
+# endif
+#endif
+}
+
+
+/* Class Confucius.
+
+   "Don't worry that other people don't know you;
+   worry that you don't know other people."            Analects--1.16.  */
+
+/* Create temporary directory with mode 0700.  Returns a dynamically
+   allocated string with the filename of the directory.  */
+static char *
+confucius_mktmpdir (void)
+{
+  int res;
+  char *tmpdir;
+
+  tmpdir = tmpnam (NULL);
+  if (!tmpdir)
+    {
+      log_error (_("cannot create temporary directory name: %s\n"),
+		 strerror (errno));
+      return NULL;
+    }
+  tmpdir = strdup (tmpdir);
+  if (!tmpdir)
+    {
+      log_error (_("cannot copy temporary directory name: %s\n"),
+		 strerror (errno));
+      return NULL;
+    }
+  res = mkdir (tmpdir, 0700);
+  if (res < 0)
+    {
+      log_error (_("cannot create temporary directory %s: %s\n"),
+		 tmpdir, strerror (errno));
+      return NULL;
+    }
+
+  return tmpdir;
+}
+
+
+/* Buffer size for I/O operations.  */
+#define CONFUCIUS_BUFSIZE 4096
+
+/* Buffer size for output lines.  */
+#define CONFUCIUS_LINESIZE 4096
+
+
+/* Copy the file IN to OUT, either of which may be "-".  */
+static int
+confucius_copy_file (const char *infile, const char *outfile)
+{
+  FILE *in;
+  int in_is_stdin = 0;
+  FILE *out;
+  int out_is_stdout = 0;
+  char data[CONFUCIUS_BUFSIZE];
+  ssize_t data_len;
+
+  if (infile[0] == '-' && infile[1] == '\0')
+    {
+      /* FIXME: Is stdin in binary mode?  */
+      in = stdin;
+      in_is_stdin = 1;
+    }
+  else
+    {
+      in = fopen (infile, "rb");
+      if (!in)
+	{
+	  log_error (_("could not open %s for writing: %s\n"),
+		     infile, strerror (errno));
+	  return 1;
+	}
+    }
+
+  if (outfile[0] == '-' && outfile[1] == '\0')
+    {
+      /* FIXME: Is stdout in binary mode?  */
+      out = stdout;
+      out_is_stdout = 1;
+    }
+  else
+    {
+      out = fopen (outfile, "wb");
+      if (!out)
+	{
+	  log_error (_("could not open %s for writing: %s\n"),
+		     infile, strerror (errno));
+	  return 1;
+	}
+    }
+
+  /* Now copy the data.  */
+  while ((data_len = fread (data, 1, sizeof (data), in)) > 0)
+    {
+      if (fwrite (data, 1, data_len, out) != data_len)
+	{
+	  log_error (_("error writing to %s: %s\n"), outfile,
+		     strerror (errno));
+	  goto copy_err;
+	}
+    }
+  if (data_len < 0 || ferror (in))
+    {
+      log_error (_("error reading from %s: %s\n"), infile, strerror (errno));
+      goto copy_err;
+    }
+
+  /* Close IN if appropriate.  */
+  if (!in_is_stdin && fclose (in) && ferror (in))
+    {
+      log_error (_("error closing %s: %s\n"), infile, strerror (errno));
+      goto copy_err;
+    }
+
+  /* Close OUT if appropriate.  */
+  if (!out_is_stdout && fclose (out) && ferror (out))
+    {
+      log_error (_("error closing %s: %s\n"), infile, strerror (errno));
+      goto copy_err;
+    }
+
+  return 0;
+
+ copy_err:
+  if (!out_is_stdout)
+    unlink (outfile);
+  return 1;
+}
+
+
+/* Get a passphrase in secure storage (if possible).  If AGAIN is
+   true, then this is a repeated attempt.  If CANCELED is not a null
+   pointer, it will be set to true or false, depending on if the user
+   canceled the operation or not.  On error (including cancelation), a
+   null pointer is returned.  The passphrase must be deallocated with
+   confucius_drop_pass.  */
+char *
+confucius_get_pass (int again, int *canceled)
+{
+  int err;
+  char *pw;
+#ifdef HAVE_LANGINFO_CODESET
+  char *orig_codeset = NULL;
+#endif
+
+  if (canceled)
+    *canceled = 0;
+  
+#ifdef ENABLE_NLS
+  /* The Assuan agent protocol requires us to transmit utf-8 strings */
+  orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL);
+#ifdef HAVE_LANGINFO_CODESET
+  if (!orig_codeset)
+    orig_codeset = nl_langinfo (CODESET);
+#endif
+  if (orig_codeset && !strcmp (orig_codeset, "UTF-8"))
+    orig_codeset = NULL;
+  if (orig_codeset)
+    {
+      /* We only switch when we are able to restore the codeset later. */
+      orig_codeset = xstrdup (orig_codeset);
+      if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8"))
+        orig_codeset = NULL; 
+    }
+#endif
+
+  pw = simple_pwquery (NULL,
+                       again ? _("does not match - try again"):NULL,
+                       _("Passphrase:"), NULL, &err);
+
+#ifdef ENABLE_NLS
+  if (orig_codeset)
+    {
+      bind_textdomain_codeset (PACKAGE_GT, orig_codeset);
+      xfree (orig_codeset);
+    }
+#endif
+
+  if (!pw)
+    {
+      if (err)
+        log_error (_("error while asking for the passphrase: %s\n"),
+                   gpg_strerror (err));
+      else
+        {
+	  log_info (_("cancelled\n"));
+	  if (canceled)
+	    *canceled = 1;
+	}      
+    }
+
+  return pw;
+}
+
+
+/* Drop a passphrase retrieved with confucius_get_pass.  */
+void
+confucius_drop_pass (char *pass)
+{
+  if (pass)
+    spwq_secure_free (pass);
+}
+
+
+/* Run a confucius crypto engine.  If MODE is oEncrypt, encryption is
+   requested.  If it is oDecrypt, decryption is requested.  INFILE and
+   OUTFILE are the temporary files used in the process.  */
+int
+confucius_process (int mode, char *infile, char *outfile)
+{
+  char *const args[] = { opt.program,
+			 mode == oEncrypt ? "-m1" : "-m2",
+			 "-q", infile,
+			 "-z", outfile,
+			 "-s", opt.keyfile,
+			 mode == oEncrypt ? "-af" : "-f",
+			 NULL };
+  int cstderr[2];
+  int master;
+  int slave;
+  int res;
+  pid_t pid;
+  pid_t wpid;
+  int tries = 0;
+
+  signal (SIGPIPE, SIG_IGN);
+
+  if (!opt.program)
+    {
+      log_error (_("no --program option provided\n"));
+      return 1;
+    }
+
+  if (mode != oDecrypt && mode != oEncrypt)
+    {
+      log_error (_("only --decrypt and --encrypt are supported\n"));
+      return 1;
+    }
+
+  if (!opt.keyfile)
+    {
+      log_error (_("no --keyfile option provided\n"));
+      return 1;
+    }
+
+  if (pipe (cstderr) < 0)
+    {
+      log_error (_("could not create pipe: %s\n"), strerror (errno));
+      return 1;
+    }
+
+  if (openpty (&master, &slave, NULL, NULL, NULL) == -1)
+    {
+      log_error (_("could not create pty: %s\n"), strerror (errno));
+      close (cstderr[0]);
+      close (cstderr[1]);
+      return -1;
+    }
+
+  /* We don't want to deal with the worst case scenarios.  */
+  assert (master > 2);
+  assert (slave > 2);
+  assert (cstderr[0] > 2);
+  assert (cstderr[1] > 2);
+
+  pid = fork ();
+  if (pid < 0)
+    {
+      log_error (_("could not fork: %s\n"), strerror (errno));
+      close (master);
+      close (slave);
+      close (cstderr[0]);
+      close (cstderr[1]);
+      return 1;
+    }
+  else if (pid == 0) 
+    {
+      /* Child.  */
+
+      /* Close the parent ends.  */
+      close (master);
+      close (cstderr[0]);
+
+      /* Change controlling terminal.  */
+      if (login_tty (slave))
+	{
+	  /* It's too early to output a debug message.  */
+	  _exit (1);
+	}
+
+      dup2 (cstderr[1], 2);
+      close (cstderr[1]);
+
+      /* Now kick off the engine program.  */
+      execv (opt.program, args);
+      log_error (_("execv failed: %s\n"), strerror (errno));
+      _exit (1);
+    }
+  else
+    {
+      /* Parent.  */
+      char buffer[CONFUCIUS_LINESIZE];
+      int buffer_len = 0;
+      fd_set fds;
+      int slave_closed = 0;
+      int stderr_closed = 0;
+
+      close (slave);
+      close (cstderr[1]);
+
+      /* Listen on the output FDs.  */
+      do
+	{
+	  FD_ZERO (&fds);
+
+	  if (!slave_closed)
+	    FD_SET (master, &fds);
+	  if (!stderr_closed)
+	    FD_SET (cstderr[0], &fds);
+
+	  res = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
+	  if (res < 0)
+	    {
+	      log_error (_("select failed: %s\n"), strerror (errno));
+
+	      kill (pid, SIGTERM);
+	      close (master);
+	      close (cstderr[0]);
+     	      return 1;
+	    }
+
+	  if (FD_ISSET (cstderr[0], &fds))
+	    {
+	      /* We got some output on stderr.  This is just passed
+		 through via the logging facility.  */
+
+	      res = read (cstderr[0], &buffer[buffer_len],
+			  sizeof (buffer) - buffer_len - 1);
+	      if (res < 0)
+		{
+		  log_error (_("read failed: %s\n"), strerror (errno));
+
+		  kill (pid, SIGTERM);
+		  close (master);
+		  close (cstderr[0]);
+		  return 1;
+		}
+	      else  
+		{
+		  char *newline;
+
+		  buffer_len += res;
+		  for (;;)
+		    {
+		      buffer[buffer_len] = '\0';
+		      newline = strchr (buffer, '\n');
+		      if (newline)
+			{
+			  *newline = '\0';
+			  log_error ("%s\n", buffer);
+			  buffer_len -= newline + 1 - buffer;
+			  memmove (buffer, newline + 1, buffer_len);
+			}
+		      else if (buffer_len == sizeof (buffer) - 1)
+			{
+			  /* Overflow.  */
+			  log_error ("%s\n", buffer);
+			  buffer_len = 0;
+			}
+		      else
+			break;
+		    }
+
+		  if (res == 0)
+		    stderr_closed = 1;
+		}
+	    }
+	  else if (FD_ISSET (master, &fds))
+	    {
+	      char data[512];
+
+	      res = read (master, data, sizeof (data));
+	      if (res < 0)
+		{
+		  if (errno == EIO)
+		    {
+		      /* Slave-side close leads to readable fd and
+			 EIO.  */
+		      slave_closed = 1;
+		    }
+		  else
+		    {
+		      log_error (_("pty read failed: %s\n"), strerror (errno));
+
+		      kill (pid, SIGTERM);
+		      close (master);
+		      close (cstderr[0]);
+		      return 1;
+		    }
+		}
+	      else if (res == 0)
+		/* This never seems to be what happens on slave-side
+		   close.  */
+		slave_closed = 1;
+	      else
+		{
+		  /* Check for password prompt.  */
+		  if (data[res - 1] == ':')
+		    {
+		      char *pass;
+		      int canceled;
+
+		      pass = confucius_get_pass (tries ? 1 : 0, &canceled);
+		      if (!pass)
+			{
+			  kill (pid, SIGTERM);
+			  close (master);
+			  close (cstderr[0]);
+			  return canceled ? 3 : 1;
+			}
+ 		      write (master, pass, strlen (pass));
+ 		      write (master, "\n", 1);
+		      confucius_drop_pass (pass);
+
+		      tries++;
+		    }
+		}
+	    }
+	}
+      while (!stderr_closed || !slave_closed);
+
+      close (master);
+      close (cstderr[0]);
+
+      wpid = waitpid (pid, &res, 0);
+      if (wpid < 0)
+	{
+	  log_error (_("waitpid failed: %s\n"), strerror (errno));
+
+	  kill (pid, SIGTERM);
+	  return 1;
+	}
+      else
+	{
+	  /* Shouldn't happen, as we don't use WNOHANG.  */
+	  assert (wpid != 0);
+
+	  if (!WIFEXITED (res))
+	    {
+	      log_error (_("child aborted with status %i\n"), res);
+	      return 1;
+	    }
+
+	  if (WEXITSTATUS (res))
+	    {
+	      /* We probably exceeded our number of attempts at guessing
+		 the password.  */
+	      if (tries >= 3)
+		return 2;
+	      else
+		return 1;
+	    }
+
+	  return 0;
+	}
+    }
+
+  /* Not reached.  */
+}
+
+
+/* Class confucius main program.  If MODE is oEncrypt, encryption is
+   requested.  If it is oDecrypt, decryption is requested.  The other
+   parameters are taken from the global option data.  */
+int
+confucius_main (int mode)
+{
+  int res;
+  char *tmpdir;
+  char *infile;
+  char *outfile;
+
+  tmpdir = confucius_mktmpdir ();
+  if (!tmpdir)
+    return 1;
+
+  /* TMPDIR + "/" + "in" + "\0".  */
+  infile = malloc (strlen (tmpdir) + 1 + 2 + 1);
+  if (!infile)
+    {
+      log_error (_("cannot allocate infile string: %s\n"), strerror (errno));
+      rmdir (tmpdir);
+      return 1;
+    }
+  strcpy (infile, tmpdir);
+  strcat (infile, "/in");
+
+  /* TMPDIR + "/" + "out" + "\0".  */
+  outfile = malloc (strlen (tmpdir) + 1 + 3 + 1);
+  if (!outfile)
+    {
+      log_error (_("cannot allocate outfile string: %s\n"), strerror (errno));
+      free (infile);
+      rmdir (tmpdir);
+      return 1;
+    }
+  strcpy (outfile, tmpdir);
+  strcat (outfile, "/out");
+
+  /* Create INFILE and fill it with content.  */
+  res = confucius_copy_file ("-", infile);
+  if (res)
+    {
+      free (outfile);
+      free (infile);
+      rmdir (tmpdir);
+      return res;
+    }
+
+  /* Run the engine and thus create the output file, handling
+     passphrase retrieval.  */
+  res = confucius_process (mode, infile, outfile);
+  if (res)
+    {
+      unlink (outfile);
+      unlink (infile);
+      free (outfile);
+      free (infile);
+      rmdir (tmpdir);
+      return res;
+    }
+
+  /* Dump the output file to stdout.  */
+  res = confucius_copy_file (outfile, "-");
+  if (res)
+    {
+      unlink (outfile);
+      unlink (infile);
+      free (outfile);
+      free (infile);
+      rmdir (tmpdir);
+      return res;
+    }
+  
+  unlink (outfile);
+  unlink (infile);
+  free (outfile);
+  free (infile);
+  rmdir (tmpdir);
+  return 0;
+}
+
+
+/* symcryptrun's entry point.  */
+int
+main (int argc, char **argv)
+{
+  ARGPARSE_ARGS pargs;
+  int no_more_options = 0;
+  int mode = 0;
+  int res;
+  char *logfile = NULL;
+
+  set_strusage (my_strusage);
+  log_set_prefix ("symcryptrun", 1);
+
+  /* Try to auto set the character set.  */
+  set_native_charset (NULL); 
+
+  i18n_init();
+
+  opt.homedir = default_homedir ();
+
+  /* Parse the command line. */
+  pargs.argc  = &argc;
+  pargs.argv  = &argv;
+  pargs.flags =  1;  /* Do not remove the args.  */
+  while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
+    {
+      switch (pargs.r_opt)
+        {
+        case oDecrypt:   mode = oDecrypt; break;
+        case oEncrypt:   mode = oEncrypt; break;
+
+	case oQuiet:     opt.quiet = 1; break;
+        case oVerbose:   opt.verbose++; break;
+        case oNoVerbose: opt.verbose = 0; break;
+        case oHomedir:   opt.homedir = pargs.r.ret_str; break;
+	  
+	case oClass:	opt.class = pargs.r.ret_str; break;
+	case oProgram:	opt.program = pargs.r.ret_str; break;
+	case oKeyfile:	opt.keyfile = pargs.r.ret_str; break;
+
+        case oLogFile:  logfile = pargs.r.ret_str; break;
+
+        default: pargs.err = 2; break;
+	}
+    }
+
+  if (!mode)
+    log_error (_("either %s or %s must be given\n"),
+               "--decrypt", "--encrypt");
+
+  if (log_get_errorcount (0))
+    exit (1);
+
+  if (logfile)
+    log_set_file (logfile);
+
+  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
+    {
+      log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
+                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
+    }
+  gcry_set_log_handler (my_gcry_logger, NULL);
+  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+
+  if (!opt.class)
+    {
+      log_error (_("no class provided\n"));
+      res = 1;
+    }
+  else if (!strcmp (opt.class, "confucius"))
+    res = confucius_main (mode);
+  else
+    {
+      log_error (_("class %s is not supported\n"), opt.class);
+      res = 1;
+    }
+
+  return res;
+}




More information about the Gnupg-commits mailing list