Updates for the recommended download of: XP Service Pack 2 (Checked Build)
[captive.git] / src / install / acquire / ui-line.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 "ui-line.h"    /* self */
23 #include <glib/gmessages.h>
24 #include "moduriload.h"
25 #include "main.h"
26 #include <unistd.h>
27 #include <time.h>
28 #include "final.h"
29
30 #ifdef HAVE_LIBREADLINE
31 #include <readline/readline.h>
32 #ifdef HAVE_READLINE_HISTORY_H
33 #include <readline/history.h>
34 #endif /* HAVE_READLINE_HISTORY_H */
35 #endif /* HAVE_LIBREADLINE */
36
37 #include <captive/macros.h>
38
39 static void print_ui_line_module_available(struct module_available *module_available)
40 {
41 gint priority_best;
42
43         g_return_if_fail(module_available!=NULL);
44         g_return_if_fail(module_available->module!=NULL);
45
46         if (G_MININT==(priority_best=captivemodid_module_type_best_priority_lookup(module_available->module->type)))
47                 printf(_("Found best available \"%s\": %s\n"),module_available->module->type,module_available->module->id);
48         else
49                 printf(_("Found although not best \"%s\" (pri=%d; best=%d): %s\n"),
50                                 module_available->module->type,module_available->module->priority,priority_best,
51                                 module_available->module->id);
52 }
53
54 static void ui_line_module_available_notify(struct module_available *module_available)
55 {
56         g_return_if_fail(module_available!=NULL);
57
58         print_ui_line_module_available(module_available);
59         printf(_("at URI: %s\n"),module_available->uri_text);
60 }
61
62 static gboolean all_modules_found=FALSE;
63
64 static void ui_line_all_modules_found_notify(void)
65 {
66         puts(_("All modules found in their best known versions."));
67         all_modules_found=TRUE;
68 }
69
70 static gboolean aborted=FALSE;
71 static time_t search_start_time;
72 static gboolean abort_msg_printed=FALSE;
73
74 static gboolean ui_line_progress(GnomeVFSURI *uri)
75 {
76 fd_set readfds;
77 struct timeval timeval;
78 static int stdin_isatty=-1;
79
80         /* 'uri' may be NULL */
81
82         if (aborted)
83                 return TRUE;
84         if (all_modules_found)
85                 return TRUE;
86
87         if (!search_start_time)
88                 search_start_time=time(NULL);
89         if (!abort_msg_printed && time(NULL)>=search_start_time+2) {
90                 puts(_("Searching... Hit ENTER to abort."));
91                 abort_msg_printed=TRUE;
92                 }
93
94         if (stdin_isatty==-1)
95                 stdin_isatty=isatty(0);
96         if (stdin_isatty>0) {
97                 FD_ZERO(&readfds);
98                 FD_SET(0,&readfds);
99                 timeval.tv_sec=0;
100                 timeval.tv_usec=0;
101                 if (1==select(1,&readfds,NULL,NULL,&timeval)) {
102                         aborted=TRUE;
103                         getchar();
104                         puts(_("*** OPERATION ABORTED ***"));
105                         return TRUE;
106                         }
107                 }
108
109         return FALSE;
110 }
111
112 static void ui_line_progress_reset(void)
113 {
114         aborted=FALSE;
115         search_start_time=0;
116         abort_msg_printed=FALSE;
117 }
118
119 static char *line_read(const gchar *prompt)
120 {
121 #ifdef HAVE_LIBREADLINE
122 char *line;
123 #else /* HAVE_LIBREADLINE */
124 char line[1024],*s;
125 #endif /* HAVE_LIBREADLINE */
126
127         g_return_val_if_fail(prompt!=NULL,NULL);
128
129         ui_line_progress_reset();
130
131 #ifdef HAVE_LIBREADLINE
132         line=readline(prompt);
133 #ifdef HAVE_ADD_HISTORY
134         if (line && *line)
135                 add_history(line);
136 #endif /* HAVE_ADD_HISTORY */
137 #else /* HAVE_LIBREADLINE */
138         fputs(prompt,stdout); fflush(stdout);
139         line=fgets(line,sizeof(line),stdin);
140 #endif /* HAVE_LIBREADLINE */
141         if (!line)
142                 return NULL;
143 #ifndef HAVE_LIBREADLINE
144         if (line && (s=strchr(line,'\n')))
145                 *s='\0';
146 #endif /* HAVE_LIBREADLINE */
147
148         return line;
149 }
150
151 /* FIXME: HACK: Encode module essentiality to '.captivemodid.xml'. */
152 struct print_modules_available_foreach_param {
153         gboolean do_print;
154         gboolean ntoskrnl_exe_found;
155         gboolean ntfs_sys_found;
156         };
157
158 static void print_modules_available_foreach
159                 (const xmlChar *type /* key */,struct module_available *module_available /* value */,
160                 struct print_modules_available_foreach_param *param /* user_data */)
161 {
162         g_return_if_fail(type!=NULL);
163         g_return_if_fail(module_available!=NULL);
164         g_return_if_fail(module_available->module!=NULL);
165         g_return_if_fail(!strcmp((const char *)type,(const char *)module_available->module->type));
166         g_return_if_fail(param!=NULL);
167
168         if (param->do_print)
169                 print_ui_line_module_available(module_available);
170
171         /**/ if (!strcmp((const char *)type,"ntoskrnl.exe"))
172                 param->ntoskrnl_exe_found=TRUE;
173         else if (!strcmp((const char *)type,"ntfs.sys"))
174                 param->ntfs_sys_found=TRUE;
175 }
176
177 /* Returns: TRUE if essential modules were found at any priority. */
178 static gboolean print_modules_available(void)
179 {
180 struct print_modules_available_foreach_param param;
181 gboolean r;
182 static gboolean first_time=TRUE;
183
184         putchar('\n');
185         param.do_print=!first_time;
186         param.ntoskrnl_exe_found=FALSE;
187         param.ntfs_sys_found=FALSE;
188         if (module_available_hash)
189                 g_hash_table_foreach(module_available_hash,(GHFunc)print_modules_available_foreach,&param);
190         r=param.ntoskrnl_exe_found && param.ntfs_sys_found;
191
192         if (!param.ntoskrnl_exe_found)
193                 printf(_("Still needed essential module: %s\n"),"ntoskrnl.exe");
194         if (!param.ntfs_sys_found)
195                 printf(_("Still needed essential module: %s\n"),"ntfs.sys");
196         if (r)
197                 puts(_(
198                                 "Essential modules (\"ntoskrnl.exe\" and \"ntfs.sys\") are available.\n"
199                                 "You may still want to get their better version and/or more modules."));
200         putchar('\n');
201
202         first_time=FALSE;
203
204         return r;
205 }
206
207 static gboolean ui_line_interactive_ask(const gchar *prompt)
208 {
209 char *line;
210 gboolean essentials_available;
211
212         if (all_modules_found)
213                 return FALSE;
214
215   essentials_available=print_modules_available();
216         puts(prompt);
217         for (;;) {
218                 line=line_read(captive_printf_alloca(_("Enter 'y' for YES, 'n' to NO%s [hit ENTER for YES]: "),
219                                 (!essentials_available ? "" : _(", 'd' if DONE"))));
220                 if (!line)
221                         return FALSE;
222                 if (!strncasecmp(line,_("yes"),strlen(line))) {
223                         free(line);
224                         return TRUE;
225                         }
226                 if (!strncasecmp(line,_("no"),strlen(line))) {
227                         free(line);
228                         return FALSE;
229                         }
230                 if (!strncasecmp(line,_("done"),strlen(line))) {
231                         putchar('\n');
232                         puts(final_text(all_modules_found));
233                         exit(EXIT_SUCCESS);
234                         }
235                 free(line);
236                 }
237         /* NOTREACHED */
238 }
239
240 static void ui_line_interactive(void)
241 {
242 #ifndef HAVE_LIBREADLINE
243         puts(_("Line editing not available, please recompile with readline library installed"));
244 #endif /* HAVE_LIBREADLINE */
245
246         if (ui_line_interactive_ask(_("Quickly scan your local disks to find needed drivers?")))
247                 scan_disks_quick();
248         while (!all_modules_found) {
249 char *line;
250
251                 if (ui_line_interactive_ask(_(
252                                 "Detection of language localized MS-Windows drivers is missing."
253                                 " You may need to copy localized ntfs.sys and ntoskrnl.exe to /var/lib/captive/ by cp(1) command;"
254                                 " contact me for their proper identification, please.\n"
255                                 "Fully scan all directories of your local disks?")))
256                         scan_disks();
257
258                 if (!all_modules_found)
259                         do {
260                                 print_modules_available();
261                                 puts(_("Do you want to enter your custom search path and/or files? You can also enter web URL."));
262                                 line=line_read(_("Enter pathname or URL [hit ENTER to skip it]: "));
263                                 if (line && *line) {
264 GnomeVFSURI *uri;
265
266                                         if (!(uri=gnome_vfs_uri_new(line)))
267                                                 printf(_("Error paring URI: %s"),line);
268                                         else {
269                                                 mod_uri_load_base_reporting(uri);
270                                                 gnome_vfs_uri_unref(uri);
271                                                 }
272                                         free(line);
273                                         }
274                                 else {
275                                         free(line);
276                                         line=NULL;
277                                         }
278                                 } while (!all_modules_found && line);
279
280                 if (ui_line_interactive_ask(_(
281                                 "You can download the best available version of needed drivers from Microsoft. They can be found in Microsoft Windows XP Service Pack 2 Checked Build.\n"
282                                 "URL: http://msdn.microsoft.com/security/productinfo/xpsp2\n"
283                                 "Legal: In some countries you need to have valid Microsoft Windows XP license to use it.\n"
284                                 "It is needed to download approx 61MB of data right now out of the 307MB file size. You can also download the file separately and load it in the previous screen if some problems occur.\n")))
285                         microsoft_com();
286                 if (!all_modules_found)
287                         puts(_("\nWe tried all available drivers acquiration methods - the options will start again."));
288                 }
289         putchar('\n');
290         puts(final_text(all_modules_found));
291 }
292
293 gboolean ui_line_init(void)
294 {
295         acquire_module_available_notify=ui_line_module_available_notify;
296         acquire_module_all_modules_found_notify=ui_line_all_modules_found_notify;
297         ui_progress=ui_line_progress;
298         ui_interactive=ui_line_interactive;
299         /* 'captivemodid_module_best_priority_notify' left NULL. */
300         return TRUE;
301 }