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