2ebc4791056a6f047e4dcb3d9bcc034796cf2163
[captive.git] / src / install / acquire / main.c
1 /* $Id$
2  * Drivers acquiring installation utility
3  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include <glib/gmessages.h>
23 #include <popt.h>
24 #include <locale.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <mntent.h>
28 #include <glib/ghash.h>
29 #include <glib/gstrfuncs.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <libgnomevfs/gnome-vfs-init.h>
34 #include "ui-line.h"
35 #include "microsoftcom.h"
36 #include <libgnomevfs/gnome-vfs-uri.h>
37 #include "diskscan.h"
38 #include "moduriload.h"
39 #include <libgnome/gnome-program.h>
40 #include <libgnomeui/gnome-ui-init.h>
41 #include <setjmp.h>
42 #include "ui-gnome.h"
43
44 #include <captive/macros.h>
45
46
47 int optarg_verbose;
48 int optarg_dry;
49 static int optarg_microsoft_com;
50 static int optarg_scan_disks;
51 static int optarg_scan_disks_quick;
52 static int optarg_text;
53 static char *optarg_modid_path=G_STRINGIFY(SYSCONFDIR) "/w32-mod-id.captivemodid.xml";
54 static GList *optarg_scan_path_list;    /* of (char *) */
55
56 static void acquire_popt_callback
57                 (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data);
58
59 static const struct poptOption popt_table[]={
60                 { argInfo:POPT_ARG_CALLBACK,arg:(void *)acquire_popt_callback },
61
62 #define BUG_ACQUIRE_POPT(shortname,longname,argInfoP,argP,valP,descripP,argDescripP) \
63                 { \
64                         longName: (longname), \
65                         shortName: (shortname), \
66                         argInfo: (argInfoP)|(!(valP) ? 0 : POPT_ARG_VAL), \
67                         arg: (void *)argP, \
68                         val: (valP), \
69                         descrip: (descripP), \
70                         argDescrip: (argDescripP), \
71                 }
72
73                 BUG_ACQUIRE_POPT(0  ,"text"            ,POPT_ARG_NONE  ,&optarg_text   ,0,
74                                 N_("Disable Gnome UI; --text must be first argument"),NULL),
75                 BUG_ACQUIRE_POPT('v',"verbose"         ,POPT_ARG_NONE  ,&optarg_verbose,0,N_("Display additional debug information"),NULL),
76                 BUG_ACQUIRE_POPT('n',"dry"             ,POPT_ARG_NONE  ,&optarg_dry    ,0,N_("No modifications, no files written"),NULL),
77                 BUG_ACQUIRE_POPT(0  ,"modid-path"      ,POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,&optarg_modid_path,0,
78                                 N_("Path to .captivemodid.xml database"),N_("path")),
79                 BUG_ACQUIRE_POPT(0  ,"scan-disks"      ,POPT_ARG_NONE  ,&optarg_scan_disks,0,N_("Scan all files on local disks"),NULL),
80                 BUG_ACQUIRE_POPT(0  ,"scan-disks-quick",POPT_ARG_NONE  ,&optarg_scan_disks_quick,0,
81                                 N_("Scan MS-Windows directories on local disks"),NULL),
82                 BUG_ACQUIRE_POPT(0  ,"scan-path" ,POPT_ARG_STRING,NULL              ,0,
83                                 N_("Scan specified disk path or web URL"),N_("path/URI")),
84                 BUG_ACQUIRE_POPT(0  ,"microsoft-com"   ,POPT_ARG_NONE  ,&optarg_microsoft_com,0,
85                                 N_("Download from microsoft.com; Legal: You may need to have valid Microsoft Windows XP license."),NULL),
86
87 #undef BUG_ACQUIRE_POPT
88                 POPT_TABLEEND
89                 };
90
91 static const struct poptOption popt_table_autohelp[]={
92                 { NULL,'\0',POPT_ARG_INCLUDE_TABLE,(struct poptOption *)&popt_table,0,PACKAGE },
93                 POPT_AUTOHELP
94                 POPT_TABLEEND
95                 };
96
97 /* poptCallbackType captive_popt_callback */
98 static void acquire_popt_callback
99                 (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data)
100 {
101         g_return_if_fail(reason==POPT_CALLBACK_REASON_OPTION);
102
103         if (opt->longName && !strcmp(opt->longName,"scan-path")) {
104                 optarg_scan_path_list=g_list_append(optarg_scan_path_list,gnome_vfs_uri_new(arg));
105                 }
106 }
107
108
109 void (*ui_interactive)(void);
110
111 static gboolean ui_progress_dummy(GnomeVFSURI *uri)
112 {
113         /* 'uri' may be NULL */
114
115         return FALSE;   /* not aborted */
116 }
117
118 gboolean (*ui_progress)(GnomeVFSURI *uri)=ui_progress_dummy;
119 void (*ui_progress_bar)(gint done,gint length);
120
121 static GList *mod_uri_list_local;
122 static void mod_uri_list_local_init(void)
123 {
124         if (mod_uri_list_local)
125                 return;
126         mod_uri_list_local=mod_uri_list();
127 }
128
129 void scan_disks_quick(void)
130 {
131 GList *mod_uri_list_quick_local,*mod_uri_l;
132
133         mod_uri_list_local_init();
134         mod_uri_list_quick_local=NULL;
135         for (mod_uri_l=mod_uri_list_local;mod_uri_l;mod_uri_l=mod_uri_l->next) {
136                 mod_uri_list_quick_local=g_list_prepend(mod_uri_list_quick_local,
137                                 gnome_vfs_uri_append_path(mod_uri_l->data,"windows/system32"));
138                 }
139         mod_uri_list_quick_local=g_list_reverse(mod_uri_list_quick_local);
140         g_list_foreach(mod_uri_list_quick_local,(GFunc)mod_uri_load,NULL);
141         gnome_vfs_uri_list_free(mod_uri_list_quick_local);
142 }
143
144 void scan_disks(void)
145 {
146         mod_uri_list_local_init();
147         g_list_foreach(mod_uri_list_local,(GFunc)mod_uri_load,NULL);
148 }
149
150 void microsoft_com(void)
151 {
152         g_list_foreach(mod_uri_microsoftcom_list(),(GFunc)mod_uri_load_base_reporting,NULL);
153 }
154
155 static void scan_batch(void)
156 {
157         g_list_foreach(optarg_scan_path_list,(GFunc)mod_uri_load_base_reporting,NULL);
158
159         if (optarg_scan_disks_quick)
160                 scan_disks_quick();
161         if (optarg_scan_disks)
162                 scan_disks();
163         if (optarg_microsoft_com)
164                 microsoft_com();
165 }
166
167 static jmp_buf gnome_init_atexit_jmpbuf;
168 static gboolean gnome_init_atexit_disable;
169
170 static void gnome_init_atexit_handler(void)
171 {
172         if (gnome_init_atexit_disable)
173                 return;
174
175         longjmp(gnome_init_atexit_jmpbuf,1);
176         g_assert_not_reached();
177         _exit(EXIT_FAILURE);
178 }
179
180 gboolean gnome_init_g_log_handler_hit;
181 static void gnome_init_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
182 {
183         gnome_init_g_log_handler_hit=TRUE;
184         g_log_default_handler(log_domain,log_level,message,user_data);
185 }
186
187 int main(int argc,char **argv)
188 {
189 poptContext context;
190 int errint;
191 gboolean is_interactive;
192 gboolean no_gnome;
193
194 #if 0
195         g_log_set_always_fatal(~(0
196                         |G_LOG_LEVEL_MESSAGE
197                         |G_LOG_LEVEL_INFO
198                         |G_LOG_LEVEL_DEBUG
199                         ));
200 #endif
201
202         /* Initialize the i18n stuff */
203         setlocale(LC_ALL,"");
204         bindtextdomain(PACKAGE,LOCALEDIR);
205         textdomain(PACKAGE);
206
207         if (!gnome_vfs_init())
208                 g_error(_("GnomeVFS failed to initialize"));
209
210         if (argv[1] && !strcmp(argv[1],"--text"))
211                 optarg_text=1;
212
213         no_gnome=(optarg_text || !getenv("DISPLAY") || !*getenv("DISPLAY"));
214
215         if (no_gnome) {
216                 context=poptGetContext(
217                                 PACKAGE,        /* name */
218                                 argc,(/*en-const*/const char **)argv,   /* argc,argv */
219                                 popt_table_autohelp,    /* options */
220                                 POPT_CONTEXT_POSIXMEHARDER);    /* flags; && !POPT_CONTEXT_KEEP_FIRST */
221                 if (context==NULL) {
222                         g_assert_not_reached(); /* argument recognization args_error */
223                         return EXIT_FAILURE;
224                         }
225                 errint=poptReadDefaultConfig(context,
226                                 TRUE);  /* useEnv */
227                 if (errint!=0) {
228                         g_assert_not_reached(); /* argument recognization args_error */
229                         return EXIT_FAILURE;
230                         }
231                 errint=poptGetNextOpt(context);
232                 if (errint!=-1) {
233                         g_assert_not_reached(); /* some non-callbacked argument reached */
234                         return EXIT_FAILURE;
235                         }
236                 if (poptPeekArg(context)) {
237                         g_error(_("No arguments expected"));
238                         return EXIT_FAILURE;
239                         }
240                 }
241         else {
242 GnomeProgram *gnome_program;
243 guint handler_id;
244
245                 gnome_init_atexit_disable=FALSE;
246                 g_atexit(gnome_init_atexit_handler);
247                 gnome_init_g_log_handler_hit=FALSE;
248                 handler_id=g_log_set_handler(
249                                 "Gtk",  /* log_domain */
250                                 G_LOG_LEVEL_WARNING,    /* log_levels */
251                                 gnome_init_g_log_handler,       /* log_func */
252                                 NULL);  /* user_data */
253                 if (!setjmp(gnome_init_atexit_jmpbuf))
254                         gnome_program=gnome_program_init(PACKAGE,VERSION,LIBGNOMEUI_MODULE,argc,argv,
255                                         GNOME_PARAM_POPT_TABLE,popt_table,
256                                         GNOME_PARAM_POPT_FLAGS,(int)POPT_CONTEXT_POSIXMEHARDER,
257                                         NULL);
258                 else {
259                         no_gnome=TRUE;
260                         /* No message: (captive-install-acquire:3693): Gtk-WARNING **: cannot open display:
261                          * was reported, probably only '--help' message was shown.
262                          */
263                         if (!gnome_init_g_log_handler_hit)
264                                 exit(EXIT_SUCCESS);
265                         }
266                 gnome_init_atexit_disable=TRUE;
267                 g_log_remove_handler(
268                                 "Gtk",  /* log_domain */
269                                 handler_id);    /* handler_id */
270                 }
271
272         is_interactive=(1
273                         && ! optarg_scan_path_list
274                         && ! optarg_scan_disks_quick
275                         && ! optarg_scan_disks 
276                         && ! optarg_microsoft_com);
277
278         /* Initialize UI here to catch all GLog errors below. */
279         if (is_interactive
280                         && (no_gnome || !ui_gnome_init())
281                         && !ui_line_init())
282                 g_error(_("No UI interface could be initialized"));
283
284         if (!captivemodid_load(optarg_modid_path) && !captivemodid_load("./w32-mod-id.captivemodid.xml"))
285                 g_error(_("Unable to load modid database: %s"),optarg_modid_path);
286
287         mod_uri_load_base_reporting(gnome_vfs_uri_new("file://" G_STRINGIFY(VARLIBCAPTIVEDIR)));
288
289         if (!is_interactive)
290                 scan_batch();
291         else
292                 (*ui_interactive)();
293
294         gnome_vfs_shutdown();
295
296         return EXIT_SUCCESS;
297 }