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