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