519d2bc6d5e24fa78336ba72a662f1ebf9a4b534
[gpgme.git] / complus / main.c
1 /* main.c - COM+ component to access GnuPG
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME 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  * GPGME 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <time.h>
29 #include <windows.h>
30
31 #include "obj_base.h"
32
33 #include "argparse.h"
34
35 #include "main.h"
36
37
38 static void register_server (void);
39 static void unregister_server (void);
40 static void enter_complus (void);
41
42
43 enum cmd_and_opt_values { aNull = 0,
44     oQuiet        = 'q',
45     oVerbose      = 'v',
46
47     oNoVerbose = 500,
48     oOptions,
49     oDebug,
50     oDebugAll,
51     oNoGreeting,
52     oNoOptions,
53     oHomedir,
54     oGPGBinary,
55     oRegServer,
56     oUnregServer,
57     oEmbedding,
58 aTest };
59
60
61 static ARGPARSE_OPTS opts[] = {
62
63     { 301, NULL, 0, N_("@Options:\n ") },
64
65     { oVerbose, "verbose",   0, N_("verbose") },
66     { oQuiet,   "quiet",     0, N_("be somewhat more quiet") },
67     { oOptions, "options"  , 2, N_("read options from file")},
68     { oDebug,   "debug"     ,4|16, N_("set debugging flags")},
69     { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
70     { oGPGBinary, "gpg-program", 2 , "@" },
71     { oRegServer, "RegServer" , 0, "@" },
72     { oUnregServer, "UnregServer" , 0, "@" },
73     { oEmbedding, "Embedding" , 0, "@" },
74 {0} };
75
76
77
78
79 static const char *
80 my_strusage( int level )
81 {
82     const char *p;
83     switch( level ) {
84       case 11: p = "gpgme";
85         break;
86       case 13: p = VERSION; break;
87       /*case 17: p = PRINTABLE_OS_NAME; break;*/
88       case 19: p =
89             _("Please report bugs to <gpgme-bugs@gnupg.org>.\n");
90         break;
91       case 1:
92       case 40:  p =
93             _("Usage: gpgme [options] (-h for help)");
94         break;
95       case 41:  p =
96             _("Syntax: gpgme [options]\n"
97               "GnuPG COM+ component\n");
98         break;
99
100       default:  p = NULL;
101     }
102     return p;
103 }
104
105
106 int
107 main (int argc, char **argv )
108 {
109     ARGPARSE_ARGS pargs;
110     int orig_argc;
111     char **orig_argv;
112     FILE *configfp = NULL;
113     char *configname = NULL;
114     unsigned configlineno;
115     int parse_debug = 0;
116     int default_config =1;
117     int greeting = 0;
118     int nogreeting = 0;
119     int action = 0;
120
121     set_strusage( my_strusage );
122     /*log_set_name ("gpa"); not yet implemented in logging.c */
123
124     opt.homedir = getenv("GNUPGHOME");
125     if( !opt.homedir || !*opt.homedir ) {
126       #ifdef HAVE_DRIVE_LETTERS
127         opt.homedir = "c:/gnupg";
128       #else
129         opt.homedir = "~/.gnupg";
130       #endif
131     }
132
133     /* check whether we have a config file on the commandline */
134     orig_argc = argc;
135     orig_argv = argv;
136     pargs.argc = &argc;
137     pargs.argv = &argv;
138     pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
139     while( arg_parse( &pargs, opts) ) {
140         if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
141             parse_debug++;
142         else if( pargs.r_opt == oOptions ) {
143             /* yes there is one, so we do not try the default one, but
144              * read the option file when it is encountered at the commandline
145              */
146             default_config = 0;
147         }
148         else if( pargs.r_opt == oNoOptions )
149             default_config = 0; /* --no-options */
150         else if( pargs.r_opt == oHomedir )
151             opt.homedir = pargs.r.ret_str;
152     }
153
154     if( default_config )
155         configname = make_filename(opt.homedir, "gpgme.conf", NULL );
156
157
158     argc = orig_argc;
159     argv = orig_argv;
160     pargs.argc = &argc;
161     pargs.argv = &argv;
162     pargs.flags=  1 | (1<<5);  /* do not remove the args, allow one dash */
163   next_pass:
164     if( configname ) {
165         configlineno = 0;
166         configfp = fopen( configname, "r" );
167         if( !configfp ) {
168             if( default_config ) {
169                 if( parse_debug )
170                     log_info(_("NOTE: no default option file `%s'\n"),
171                                                             configname );
172             }
173             else {
174                 log_error(_("option file `%s': %s\n"),
175                                     configname, strerror(errno) );
176                 exit(2);
177             }
178             free(configname); configname = NULL;
179         }
180         if( parse_debug && configname )
181             log_info(_("reading options from `%s'\n"), configname );
182         default_config = 0;
183     }
184
185     while( optfile_parse( configfp, configname, &configlineno,
186                                                 &pargs, opts) ) {
187         switch( pargs.r_opt ) {
188           case oQuiet: opt.quiet = 1; break;
189           case oVerbose: opt.verbose++; break;
190
191           case oDebug: opt.debug |= pargs.r.ret_ulong; break;
192           case oDebugAll: opt.debug = ~0; break;
193
194           case oOptions:
195             /* config files may not be nested (silently ignore them) */
196             if( !configfp ) {
197                 free(configname);
198                 configname = xstrdup(pargs.r.ret_str);
199                 goto next_pass;
200             }
201             break;
202           case oNoGreeting: nogreeting = 1; break;
203           case oNoVerbose: opt.verbose = 0; break;
204           case oNoOptions: break; /* no-options */
205           case oHomedir: opt.homedir = pargs.r.ret_str; break;
206           case oGPGBinary:  break;
207
208           case oRegServer: action = 1; break;
209           case oUnregServer: action = 2; break;
210           case oEmbedding: action = 3; break;
211
212           default : pargs.err = configfp? 1:2; break;
213         }
214     }
215     if( configfp ) {
216         fclose( configfp );
217         configfp = NULL;
218         free(configname); configname = NULL;
219         goto next_pass;
220     }
221     free( configname ); configname = NULL;
222     if( log_get_errorcount(0) )
223         exit(2);
224     if( nogreeting )
225         greeting = 0;
226
227     if( greeting ) {
228         fprintf(stderr, "%s %s; %s\n",
229                         strusage(11), strusage(13), strusage(14) );
230         fprintf(stderr, "%s\n", strusage(15) );
231     }
232   #ifdef IS_DEVELOPMENT_VERSION
233     log_info("NOTE: this is a development version!\n");
234   #endif
235
236     if ( action == 1 )
237         register_server ();
238     else if (action == 2 )
239         unregister_server ();
240     else if (action == 3 )
241         enter_complus ();
242     else {
243         fprintf (stderr, "This is a COM+ component with no user interface.\n"
244                  "gpgme --help will give you a list of options\n" );
245         exit (1);
246     }
247
248     return 0;
249 }
250
251 static void
252 register_server ()
253 {
254 }
255
256 static void
257 unregister_server ()
258 {
259 }
260
261 static void
262 enter_complus ()
263 {
264     HANDLE running;
265     int reg;
266     IClassFactory *factory;
267     CLSID clsid;
268
269     CoInitializeEx (NULL, COINIT_MULTITHREADED); 
270     running = CreateEvent (NULL, FALSE, FALSE, NULL );
271
272     factory = gnupg_factory_new ( &clsid ); 
273     CoRegisterClassObject (&clsid, (IUnknown*)factory, 
274                            CLSCTX_LOCAL_SERVER,
275                            REGCLS_SUSPENDED|REGCLS_MULTIPLEUSE, &reg );
276     CoResumeClassObjects ();
277
278     WaitForSingleObject ( running, INFINITE );
279     CloseHandle (running);
280     CoRevokeClassObject ( reg );
281     gnupg_factory_release (factory);
282     CoUninitialize (); 
283 }
284
285