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