Improved logging for error orginating from libgcrypt.
[gnupg.git] / tools / symcryptrun.c
1 /* symcryptrun.c - Tool to call simple symmetric encryption tools.
2  *      Copyright (C) 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22
23 /* Sometimes simple encryption tools are already in use for a long
24    time and there is a desire to integrate them into the GnuPG
25    framework.  The protocols and encryption methods might be
26    non-standard or not even properly documented, so that a
27    full-fledged encryption tool with an interface like gpg is not
28    doable.  This simple wrapper program provides a solution: It
29    operates by calling the encryption/decryption module and providing
30    the passphrase for a key (or even the key directly) using the
31    standard pinentry mechanism through gpg-agent.  */
32
33 /* This program is invoked in the following way:
34
35    symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE \
36      [--decrypt | --encrypt]
37
38    For encryption, the plain text must be provided on STDIN, and the
39    ciphertext will be output to STDOUT.  For decryption vice versa.
40
41    CLASS can currently only be "confucius".
42
43    PROGRAM must be the path to the crypto engine.
44
45    KEYFILE must contain the secret key, which may be protected by a
46    passphrase.  The passphrase is retrieved via the pinentry program.
47
48
49    The GPG Agent _must_ be running before starting symcryptrun.
50
51    The possible exit status codes:
52
53    0    Success
54    1    Some error occured
55    2    No valid passphrase was provided
56    3    The operation was canceled by the user
57
58    Other classes may be added in the future.  */
59
60 #define SYMC_BAD_PASSPHRASE     2
61 #define SYMC_CANCELED           3
62
63 \f
64 #include <config.h>
65
66 #include <unistd.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <errno.h>
71 #include <assert.h>
72 #include <signal.h>
73 #include <sys/stat.h>
74 #include <sys/types.h>
75 #include <sys/wait.h>
76 #ifdef HAVE_PTY_H
77 #include <pty.h>
78 #endif
79 #include <utmp.h>
80 #include <ctype.h>
81 #ifdef HAVE_LOCALE_H
82 #include <locale.h>
83 #endif
84 #ifdef HAVE_LANGINFO_CODESET
85 #include <langinfo.h>
86 #endif
87 #include <gpg-error.h>
88
89 #define JNLIB_NEED_LOG_LOGV
90 #include "i18n.h"
91 #include "../common/util.h"
92 #include "mkdtemp.h"
93
94 /* FIXME: Bah.  For spwq_secure_free.  */
95 #define SIMPLE_PWQUERY_IMPLEMENTATION 1
96 #include "../common/simple-pwquery.h"
97
98 \f
99 /* From simple-gettext.c.  */
100
101 /* We assume to have `unsigned long int' value with at least 32 bits.  */
102 #define HASHWORDBITS 32
103
104 /* The so called `hashpjw' function by P.J. Weinberger
105    [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
106    1986, 1987 Bell Telephone Laboratories, Inc.]  */
107
108 static __inline__ ulong
109 hash_string( const char *str_param )
110 {
111     unsigned long int hval, g;
112     const char *str = str_param;
113
114     hval = 0;
115     while (*str != '\0')
116     {
117         hval <<= 4;
118         hval += (unsigned long int) *str++;
119         g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
120         if (g != 0)
121         {
122           hval ^= g >> (HASHWORDBITS - 8);
123           hval ^= g;
124         }
125     }
126     return hval;
127 }
128
129 \f
130 /* Constants to identify the commands and options. */
131 enum cmd_and_opt_values
132   {
133     aNull = 0,
134     oQuiet      = 'q',
135     oVerbose    = 'v',
136
137     oNoVerbose  = 500,
138     oOptions,
139     oNoOptions,
140     oLogFile,
141     oHomedir,
142     oClass,
143     oProgram,
144     oKeyfile,
145     oDecrypt,
146     oEncrypt,
147     oInput
148   };
149
150
151 /* The list of commands and options.  */
152 static ARGPARSE_OPTS opts[] =
153   {
154     { 301, NULL, 0, N_("@\nCommands:\n ") },
155
156     { oDecrypt, "decrypt", 0, N_("decryption modus") },
157     { oEncrypt, "encrypt", 0, N_("encryption modus") },
158     
159     { 302, NULL, 0, N_("@\nOptions:\n ") },
160     
161     { oClass, "class", 2, N_("tool class (confucius)") },
162     { oProgram, "program", 2, N_("program filename") },
163
164     { oKeyfile, "keyfile", 2, N_("secret key file (required)") },
165     { oInput, "inputfile", 2, N_("input file name (default stdin)") },
166     { oVerbose, "verbose",  0, N_("verbose") },
167     { oQuiet, "quiet",      0, N_("quiet") },
168     { oLogFile, "log-file", 2, N_("use a log file for the server") },
169     { oOptions,  "options"  , 2, N_("|FILE|read options from FILE") },
170
171     /* Hidden options.  */
172     { oNoVerbose, "no-verbose",  0, "@" },
173     { oHomedir, "homedir", 2, "@" },   
174     { oNoOptions, "no-options", 0, "@" },/* shortcut for --options /dev/null */
175
176     {0}
177   };
178
179
180 /* We keep all global options in the structure OPT.  */
181 struct
182 {
183   int verbose;          /* Verbosity level.  */
184   int quiet;            /* Be extra quiet.  */
185   const char *homedir;  /* Configuration directory name */
186
187   char *class;
188   char *program;
189   char *keyfile;
190   char *input;
191 } opt;
192
193 \f
194 /* Print usage information and and provide strings for help.  */
195 static const char *
196 my_strusage (int level)
197 {
198   const char *p;
199
200   switch (level)
201     {
202     case 11: p = "symcryptrun (GnuPG)";
203       break;
204     case 13: p = VERSION; break;
205     case 17: p = PRINTABLE_OS_NAME; break;
206     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
207       break;
208     case 1:
209     case 40: p = _("Usage: symcryptrun [options] (-h for help)");
210       break;
211     case 41:
212       p = _("Syntax: symcryptrun --class CLASS --program PROGRAM "
213             "--keyfile KEYFILE [options...] COMMAND [inputfile]\n"
214             "Call a simple symmetric encryption tool\n");
215       break;
216     case 31: p = "\nHome: "; break;
217     case 32: p = opt.homedir; break;
218     case 33: p = "\n"; break;
219
220     default: p = NULL; break;
221     }
222   return p;
223 }
224
225
226 /* Initialize the gettext system.  */
227 static void
228 i18n_init(void)
229 {
230 #ifdef USE_SIMPLE_GETTEXT
231   set_gettext_file (PACKAGE_GT);
232 #else
233 # ifdef ENABLE_NLS
234   setlocale (LC_ALL, "");
235   bindtextdomain (PACKAGE_GT, LOCALEDIR);
236   textdomain (PACKAGE_GT);
237 # endif
238 #endif
239 }
240
241 \f
242 /* This is in the GNU C library in unistd.h.  */
243
244 #ifndef TEMP_FAILURE_RETRY
245 /* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno'
246    set to EINTR.  */
247
248 # define TEMP_FAILURE_RETRY(expression) \
249   (__extension__                                                              \
250     ({ long int __result;                                                     \
251        do __result = (long int) (expression);                                 \
252        while (__result == -1L && errno == EINTR);                             \
253        __result; }))
254 #endif
255
256
257 /* Unlink a file, and shred it if SHRED is true.  */
258 int
259 remove_file (char *name, int shred)
260 {
261   if (!shred)
262     return unlink (name);
263   else
264     {
265       int status;
266       pid_t pid;
267
268       pid = fork ();
269       if (pid == 0)
270         {
271           /* Child.  */
272           
273           /* -f forces file to be writable, and -u unlinks it afterwards.  */
274           char *args[] = { SHRED, "-uf", name, NULL };
275           
276           execv (SHRED, args);
277           _exit (127);
278         }
279       else if (pid < 0)
280         {
281           /* Fork failed.  */
282           status = -1;
283         }
284       else
285         {
286           /* Parent.  */
287           
288           if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
289             status = -1;
290         }
291       
292       if (!WIFEXITED (status))
293         {
294           log_error (_("%s on %s aborted with status %i\n"),
295                      SHRED, name, status);
296           unlink (name);
297           return 1;
298         }
299       else if (WEXITSTATUS (status))
300         {
301           log_error (_("%s on %s failed with status %i\n"), SHRED, name,
302                      WEXITSTATUS (status));
303           unlink (name);
304           return 1;
305         }
306
307       return 0;
308     }
309 }
310
311 \f
312 /* Class Confucius.
313
314    "Don't worry that other people don't know you;
315    worry that you don't know other people."            Analects--1.16.  */
316
317 /* Create temporary directory with mode 0700.  Returns a dynamically
318    allocated string with the filename of the directory.  */
319 static char *
320 confucius_mktmpdir (void)
321 {
322   char *name;
323
324   name = strdup ("/tmp/gpg-XXXXXX");
325   if (!name || !mkdtemp (name))
326     {
327       log_error (_("can't create temporary directory `%s': %s\n"),
328                  name?name:"", strerror (errno));
329       return NULL;
330     }
331
332   return name;
333 }
334
335
336 /* Buffer size for I/O operations.  */
337 #define CONFUCIUS_BUFSIZE 4096
338
339 /* Buffer size for output lines.  */
340 #define CONFUCIUS_LINESIZE 4096
341
342
343 /* Copy the file IN to OUT, either of which may be "-".  If PLAIN is
344    true, and the copying fails, and OUT is not STDOUT, then shred the
345    file instead unlinking it.  */
346 static int
347 confucius_copy_file (char *infile, char *outfile, int plain)
348 {
349   FILE *in;
350   int in_is_stdin = 0;
351   FILE *out;
352   int out_is_stdout = 0;
353   char data[CONFUCIUS_BUFSIZE];
354   ssize_t data_len;
355
356   if (infile[0] == '-' && infile[1] == '\0')
357     {
358       /* FIXME: Is stdin in binary mode?  */
359       in = stdin;
360       in_is_stdin = 1;
361     }
362   else
363     {
364       in = fopen (infile, "rb");
365       if (!in)
366         {
367           log_error (_("could not open %s for writing: %s\n"),
368                      infile, strerror (errno));
369           return 1;
370         }
371     }
372
373   if (outfile[0] == '-' && outfile[1] == '\0')
374     {
375       /* FIXME: Is stdout in binary mode?  */
376       out = stdout;
377       out_is_stdout = 1;
378     }
379   else
380     {
381       out = fopen (outfile, "wb");
382       if (!out)
383         {
384           log_error (_("could not open %s for writing: %s\n"),
385                      infile, strerror (errno));
386           return 1;
387         }
388     }
389
390   /* Now copy the data.  */
391   while ((data_len = fread (data, 1, sizeof (data), in)) > 0)
392     {
393       if (fwrite (data, 1, data_len, out) != data_len)
394         {
395           log_error (_("error writing to %s: %s\n"), outfile,
396                      strerror (errno));
397           goto copy_err;
398         }
399     }
400   if (data_len < 0 || ferror (in))
401     {
402       log_error (_("error reading from %s: %s\n"), infile, strerror (errno));
403       goto copy_err;
404     }
405
406   /* Close IN if appropriate.  */
407   if (!in_is_stdin && fclose (in) && ferror (in))
408     {
409       log_error (_("error closing %s: %s\n"), infile, strerror (errno));
410       goto copy_err;
411     }
412
413   /* Close OUT if appropriate.  */
414   if (!out_is_stdout && fclose (out) && ferror (out))
415     {
416       log_error (_("error closing %s: %s\n"), infile, strerror (errno));
417       goto copy_err;
418     }
419
420   return 0;
421
422  copy_err:
423   if (!out_is_stdout)
424     remove_file (outfile, plain);
425
426   return 1;
427 }
428
429
430 /* Get a passphrase in secure storage (if possible).  If AGAIN is
431    true, then this is a repeated attempt.  If CANCELED is not a null
432    pointer, it will be set to true or false, depending on if the user
433    canceled the operation or not.  On error (including cancelation), a
434    null pointer is returned.  The passphrase must be deallocated with
435    confucius_drop_pass.  CACHEID is the ID to be used for passphrase
436    caching and can be NULL to disable caching.  */
437 char *
438 confucius_get_pass (const char *cacheid, int again, int *canceled)
439 {
440   int err;
441   char *pw;
442 #ifdef HAVE_LANGINFO_CODESET
443   char *orig_codeset = NULL;
444 #endif
445
446   if (canceled)
447     *canceled = 0;
448   
449 #ifdef ENABLE_NLS
450   /* The Assuan agent protocol requires us to transmit utf-8 strings */
451   orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL);
452 #ifdef HAVE_LANGINFO_CODESET
453   if (!orig_codeset)
454     orig_codeset = nl_langinfo (CODESET);
455 #endif
456   if (orig_codeset && !strcmp (orig_codeset, "UTF-8"))
457     orig_codeset = NULL;
458   if (orig_codeset)
459     {
460       /* We only switch when we are able to restore the codeset later. */
461       orig_codeset = xstrdup (orig_codeset);
462       if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8"))
463         orig_codeset = NULL; 
464     }
465 #endif
466
467   pw = simple_pwquery (cacheid,
468                        again ? _("does not match - try again"):NULL,
469                        _("Passphrase:"), NULL, 0, &err);
470
471 #ifdef ENABLE_NLS
472   if (orig_codeset)
473     {
474       bind_textdomain_codeset (PACKAGE_GT, orig_codeset);
475       xfree (orig_codeset);
476     }
477 #endif
478
479   if (!pw)
480     {
481       if (err)
482         log_error (_("error while asking for the passphrase: %s\n"),
483                    gpg_strerror (err));
484       else
485         {
486           log_info (_("cancelled\n"));
487           if (canceled)
488             *canceled = 1;
489         }      
490     }
491
492   return pw;
493 }
494
495
496 /* Drop a passphrase retrieved with confucius_get_pass.  */
497 void
498 confucius_drop_pass (char *pass)
499 {
500   if (pass)
501     spwq_secure_free (pass);
502 }
503
504
505 /* Run a confucius crypto engine.  If MODE is oEncrypt, encryption is
506    requested.  If it is oDecrypt, decryption is requested.  INFILE and
507    OUTFILE are the temporary files used in the process.  */
508 int
509 confucius_process (int mode, char *infile, char *outfile,
510                    int argc, char *argv[])
511 {
512   char **args;
513   int cstderr[2];
514   int master;
515   int slave;
516   int res;
517   pid_t pid;
518   pid_t wpid;
519   int tries = 0;
520   char cacheid[40];
521
522   signal (SIGPIPE, SIG_IGN);
523
524   if (!opt.program)
525     {
526       log_error (_("no --program option provided\n"));
527       return 1;
528     }
529
530   if (mode != oDecrypt && mode != oEncrypt)
531     {
532       log_error (_("only --decrypt and --encrypt are supported\n"));
533       return 1;
534     }
535
536   if (!opt.keyfile)
537     {
538       log_error (_("no --keyfile option provided\n"));
539       return 1;
540     }
541
542   /* Generate a hash from the keyfile name for caching.  */
543   snprintf (cacheid, sizeof (cacheid), "confucius:%lu",
544             hash_string (opt.keyfile));
545   cacheid[sizeof (cacheid) - 1] = '\0';
546   args = malloc (sizeof (char *) * (10 + argc));
547   if (!args)
548     {
549       log_error (_("cannot allocate args vector\n"));
550       return 1;
551     }
552   args[0] = opt.program;
553   args[1] = (mode == oEncrypt) ? "-m1" : "-m2";
554   args[2] = "-q";
555   args[3] = infile;
556   args[4] = "-z";
557   args[5] = outfile;
558   args[6] = "-s";
559   args[7] = opt.keyfile;
560   args[8] = (mode == oEncrypt) ? "-af" : "-f";
561   args[9 + argc] = NULL;
562   while (argc--)
563     args[9 + argc] = argv[argc];
564
565   if (pipe (cstderr) < 0)
566     {
567       log_error (_("could not create pipe: %s\n"), strerror (errno));
568       free (args);
569       return 1;
570     }
571
572   if (openpty (&master, &slave, NULL, NULL, NULL) == -1)
573     {
574       log_error (_("could not create pty: %s\n"), strerror (errno));
575       close (cstderr[0]);
576       close (cstderr[1]);
577       free (args);
578       return -1;
579     }
580
581   /* We don't want to deal with the worst case scenarios.  */
582   assert (master > 2);
583   assert (slave > 2);
584   assert (cstderr[0] > 2);
585   assert (cstderr[1] > 2);
586
587   pid = fork ();
588   if (pid < 0)
589     {
590       log_error (_("could not fork: %s\n"), strerror (errno));
591       close (master);
592       close (slave);
593       close (cstderr[0]);
594       close (cstderr[1]);
595       free (args);
596       return 1;
597     }
598   else if (pid == 0) 
599     {
600       /* Child.  */
601
602       /* Close the parent ends.  */
603       close (master);
604       close (cstderr[0]);
605
606       /* Change controlling terminal.  */
607       if (login_tty (slave))
608         {
609           /* It's too early to output a debug message.  */
610           _exit (1);
611         }
612
613       dup2 (cstderr[1], 2);
614       close (cstderr[1]);
615
616       /* Now kick off the engine program.  */
617       execv (opt.program, args);
618       log_error (_("execv failed: %s\n"), strerror (errno));
619       _exit (1);
620     }
621   else
622     {
623       /* Parent.  */
624       char buffer[CONFUCIUS_LINESIZE];
625       int buffer_len = 0;
626       fd_set fds;
627       int slave_closed = 0;
628       int stderr_closed = 0;
629
630       close (slave);
631       close (cstderr[1]);
632       free (args);
633
634       /* Listen on the output FDs.  */
635       do
636         {
637           FD_ZERO (&fds);
638
639           if (!slave_closed)
640             FD_SET (master, &fds);
641           if (!stderr_closed)
642             FD_SET (cstderr[0], &fds);
643
644           res = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
645           if (res < 0)
646             {
647               log_error (_("select failed: %s\n"), strerror (errno));
648
649               kill (pid, SIGTERM);
650               close (master);
651               close (cstderr[0]);
652               return 1;
653             }
654
655           if (FD_ISSET (cstderr[0], &fds))
656             {
657               /* We got some output on stderr.  This is just passed
658                  through via the logging facility.  */
659
660               res = read (cstderr[0], &buffer[buffer_len],
661                           sizeof (buffer) - buffer_len - 1);
662               if (res < 0)
663                 {
664                   log_error (_("read failed: %s\n"), strerror (errno));
665
666                   kill (pid, SIGTERM);
667                   close (master);
668                   close (cstderr[0]);
669                   return 1;
670                 }
671               else  
672                 {
673                   char *newline;
674
675                   buffer_len += res;
676                   for (;;)
677                     {
678                       buffer[buffer_len] = '\0';
679                       newline = strchr (buffer, '\n');
680                       if (newline)
681                         {
682                           *newline = '\0';
683                           log_error ("%s\n", buffer);
684                           buffer_len -= newline + 1 - buffer;
685                           memmove (buffer, newline + 1, buffer_len);
686                         }
687                       else if (buffer_len == sizeof (buffer) - 1)
688                         {
689                           /* Overflow.  */
690                           log_error ("%s\n", buffer);
691                           buffer_len = 0;
692                         }
693                       else
694                         break;
695                     }
696
697                   if (res == 0)
698                     stderr_closed = 1;
699                 }
700             }
701           else if (FD_ISSET (master, &fds))
702             {
703               char data[512];
704
705               res = read (master, data, sizeof (data));
706               if (res < 0)
707                 {
708                   if (errno == EIO)
709                     {
710                       /* Slave-side close leads to readable fd and
711                          EIO.  */
712                       slave_closed = 1;
713                     }
714                   else
715                     {
716                       log_error (_("pty read failed: %s\n"), strerror (errno));
717
718                       kill (pid, SIGTERM);
719                       close (master);
720                       close (cstderr[0]);
721                       return 1;
722                     }
723                 }
724               else if (res == 0)
725                 /* This never seems to be what happens on slave-side
726                    close.  */
727                 slave_closed = 1;
728               else
729                 {
730                   /* Check for password prompt.  */
731                   if (data[res - 1] == ':')
732                     {
733                       char *pass;
734                       int canceled;
735
736                       /* If this is not the first attempt, the
737                          passphrase seems to be wrong, so clear the
738                          cache.  */
739                       if (tries)
740                         simple_pwclear (cacheid);
741
742                       pass = confucius_get_pass (cacheid,
743                                                  tries ? 1 : 0, &canceled);
744                       if (!pass)
745                         {
746                           kill (pid, SIGTERM);
747                           close (master);
748                           close (cstderr[0]);
749                           return canceled ? SYMC_CANCELED : 1;
750                         }
751                       write (master, pass, strlen (pass));
752                       write (master, "\n", 1);
753                       confucius_drop_pass (pass);
754
755                       tries++;
756                     }
757                 }
758             }
759         }
760       while (!stderr_closed || !slave_closed);
761
762       close (master);
763       close (cstderr[0]);
764
765       wpid = waitpid (pid, &res, 0);
766       if (wpid < 0)
767         {
768           log_error (_("waitpid failed: %s\n"), strerror (errno));
769
770           kill (pid, SIGTERM);
771           /* State of cached password is unclear.  Just remove it.  */
772           simple_pwclear (cacheid);
773           return 1;
774         }
775       else
776         {
777           /* Shouldn't happen, as we don't use WNOHANG.  */
778           assert (wpid != 0);
779
780           if (!WIFEXITED (res))
781             {
782               log_error (_("child aborted with status %i\n"), res);
783
784               /* State of cached password is unclear.  Just remove it.  */
785               simple_pwclear (cacheid);
786
787               return 1;
788             }
789
790           if (WEXITSTATUS (res))
791             {
792               /* The passphrase was wrong.  Remove it from the cache.  */
793               simple_pwclear (cacheid);
794
795               /* We probably exceeded our number of attempts at guessing
796                  the password.  */
797               if (tries >= 3)
798                 return SYMC_BAD_PASSPHRASE;
799               else
800                 return 1;
801             }
802
803           return 0;
804         }
805     }
806
807   /* Not reached.  */
808 }
809
810
811 /* Class confucius main program.  If MODE is oEncrypt, encryption is
812    requested.  If it is oDecrypt, decryption is requested.  The other
813    parameters are taken from the global option data.  */
814 int
815 confucius_main (int mode, int argc, char *argv[])
816 {
817   int res;
818   char *tmpdir;
819   char *infile;
820   int infile_from_stdin = 0;
821   char *outfile;
822
823   tmpdir = confucius_mktmpdir ();
824   if (!tmpdir)
825     return 1;
826
827   if (opt.input && !(opt.input[0] == '-' && opt.input[1] == '\0'))
828     infile = xstrdup (opt.input);
829   else
830     {
831       infile_from_stdin = 1;
832
833       /* TMPDIR + "/" + "in" + "\0".  */
834       infile = malloc (strlen (tmpdir) + 1 + 2 + 1);
835       if (!infile)
836         {
837           log_error (_("cannot allocate infile string: %s\n"),
838                      strerror (errno));
839           rmdir (tmpdir);
840           return 1;
841         }
842       strcpy (infile, tmpdir);
843       strcat (infile, "/in");
844     }
845
846   /* TMPDIR + "/" + "out" + "\0".  */
847   outfile = malloc (strlen (tmpdir) + 1 + 3 + 1);
848   if (!outfile)
849     {
850       log_error (_("cannot allocate outfile string: %s\n"), strerror (errno));
851       free (infile);
852       rmdir (tmpdir);
853       return 1;
854     }
855   strcpy (outfile, tmpdir);
856   strcat (outfile, "/out");
857
858   if (infile_from_stdin)
859     {
860       /* Create INFILE and fill it with content.  */
861       res = confucius_copy_file ("-", infile, mode == oEncrypt);
862       if (res)
863         {
864           free (outfile);
865           free (infile);
866           rmdir (tmpdir);
867           return res;
868         }
869     }
870
871   /* Run the engine and thus create the output file, handling
872      passphrase retrieval.  */
873   res = confucius_process (mode, infile, outfile, argc, argv);
874   if (res)
875     {
876       remove_file (outfile, mode == oDecrypt);
877       if (infile_from_stdin)
878         remove_file (infile, mode == oEncrypt);
879       free (outfile);
880       free (infile);
881       rmdir (tmpdir);
882       return res;
883     }
884
885   /* Dump the output file to stdout.  */
886   res = confucius_copy_file (outfile, "-", mode == oDecrypt);
887   if (res)
888     {
889       remove_file (outfile, mode == oDecrypt);
890       if (infile_from_stdin)
891         remove_file (infile, mode == oEncrypt);
892       free (outfile);
893       free (infile);
894       rmdir (tmpdir);
895       return res;
896     }
897   
898   remove_file (outfile, mode == oDecrypt);
899   if (infile_from_stdin)
900     remove_file (infile, mode == oEncrypt);
901   free (outfile);
902   free (infile);
903   rmdir (tmpdir);
904   return 0;
905 }
906
907 \f
908 /* symcryptrun's entry point.  */
909 int
910 main (int argc, char **argv)
911 {
912   ARGPARSE_ARGS pargs;
913   int orig_argc;
914   char **orig_argv;
915   FILE *configfp = NULL;
916   char *configname = NULL;
917   unsigned configlineno; 
918   int mode = 0;
919   int res;
920   char *logfile = NULL;
921   int default_config = 1;
922
923   set_strusage (my_strusage);
924   log_set_prefix ("symcryptrun", 1);
925
926   /* Try to auto set the character set.  */
927   set_native_charset (NULL); 
928
929   i18n_init();
930
931   opt.homedir = default_homedir ();
932
933   /* Check whether we have a config file given on the commandline */
934   orig_argc = argc;
935   orig_argv = argv;
936   pargs.argc = &argc;
937   pargs.argv = &argv;
938   pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
939   while (arg_parse( &pargs, opts))
940     {
941       if (pargs.r_opt == oOptions)
942         { /* Yes there is one, so we do not try the default one, but
943              read the option file when it is encountered at the
944              commandline */
945           default_config = 0;
946         }
947       else if (pargs.r_opt == oNoOptions)
948         default_config = 0; /* --no-options */
949       else if (pargs.r_opt == oHomedir)
950         opt.homedir = pargs.r.ret_str;
951     }
952
953   if (default_config)
954     configname = make_filename (opt.homedir, "symcryptrun.conf", NULL );
955   
956   argc = orig_argc;
957   argv = orig_argv;
958   pargs.argc = &argc;
959   pargs.argv = &argv;
960   pargs.flags= 1;  /* do not remove the args */
961  next_pass:
962   if (configname)
963     {
964       configlineno = 0;
965       configfp = fopen (configname, "r");
966       if (!configfp)
967         {
968           if (!default_config)
969             {
970               log_error (_("option file `%s': %s\n"),
971                          configname, strerror(errno) );
972               exit(1);
973             }
974           xfree (configname); 
975           configname = NULL;
976         }
977       default_config = 0;
978     }
979
980   /* Parse the command line. */
981   while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
982     {
983       switch (pargs.r_opt)
984         {
985         case oDecrypt:   mode = oDecrypt; break;
986         case oEncrypt:   mode = oEncrypt; break;
987
988         case oQuiet:     opt.quiet = 1; break;
989         case oVerbose:   opt.verbose++; break;
990         case oNoVerbose: opt.verbose = 0; break;
991           
992         case oClass:    opt.class = pargs.r.ret_str; break;
993         case oProgram:  opt.program = pargs.r.ret_str; break;
994         case oKeyfile:  opt.keyfile = pargs.r.ret_str; break;
995         case oInput:    opt.input = pargs.r.ret_str; break;
996
997         case oLogFile:  logfile = pargs.r.ret_str; break;
998
999         case oOptions:
1000           /* Config files may not be nested (silently ignore them) */
1001           if (!configfp)
1002             {
1003                 xfree(configname);
1004                 configname = xstrdup(pargs.r.ret_str);
1005                 goto next_pass;
1006             }
1007           break;
1008         case oNoOptions: break; /* no-options */
1009         case oHomedir: /* Ignore this option here. */; break;
1010
1011         default : pargs.err = configfp? 1:2; break;
1012         }
1013     }
1014   if (configfp)
1015     {
1016       fclose( configfp );
1017       configfp = NULL;
1018       configname = NULL;
1019       goto next_pass;
1020     }
1021   xfree (configname);
1022   configname = NULL;
1023
1024   if (!mode)
1025     log_error (_("either %s or %s must be given\n"),
1026                "--decrypt", "--encrypt");
1027
1028   if (log_get_errorcount (0))
1029     exit (1);
1030
1031   if (logfile)
1032     log_set_file (logfile);
1033
1034   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
1035   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
1036     {
1037       log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
1038                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
1039     }
1040   setup_libgcrypt_logging ();
1041   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1042
1043   if (!opt.class)
1044     {
1045       log_error (_("no class provided\n"));
1046       res = 1;
1047     }
1048   else if (!strcmp (opt.class, "confucius"))
1049     res = confucius_main (mode, argc, argv);
1050   else
1051     {
1052       log_error (_("class %s is not supported\n"), opt.class);
1053       res = 1;
1054     }
1055
1056   return res;
1057 }