788fb8606c93b8f225cc14144ba742335f516564
[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
79         /* 'uri' may be NULL */
80
81         if (aborted)
82                 return TRUE;
83         if (all_modules_found)
84                 return TRUE;
85
86         if (!search_start_time)
87                 search_start_time=time(NULL);
88         if (!abort_msg_printed && time(NULL)>=search_start_time+2) {
89                 puts(_("Searching... Hit ENTER to abort."));
90                 abort_msg_printed=TRUE;
91                 }
92
93         if (isatty(0)) {
94                 FD_ZERO(&readfds);
95                 FD_SET(0,&readfds);
96                 timeval.tv_sec=0;
97                 timeval.tv_usec=0;
98                 if (1==select(1,&readfds,NULL,NULL,&timeval)) {
99                         aborted=TRUE;
100                         getchar();
101                         puts(_("*** OPERATION ABORTED ***"));
102                         return TRUE;
103                         }
104                 }
105
106         return FALSE;
107 }
108
109 static void ui_line_progress_reset(void)
110 {
111         aborted=FALSE;
112         search_start_time=0;
113         abort_msg_printed=FALSE;
114 }
115
116 static char *line_read(const gchar *prompt)
117 {
118 #ifdef HAVE_LIBREADLINE
119 char *line;
120 #else /* HAVE_LIBREADLINE */
121 char line[1024],*s;
122 #endif /* HAVE_LIBREADLINE */
123
124         g_return_val_if_fail(prompt!=NULL,NULL);
125
126         ui_line_progress_reset();
127
128 #ifdef HAVE_LIBREADLINE
129         line=readline(prompt);
130 #ifdef HAVE_ADD_HISTORY
131         if (line && *line)
132                 add_history(line);
133 #endif /* HAVE_ADD_HISTORY */
134 #else /* HAVE_LIBREADLINE */
135         fputs(prompt,stdout); fflush(stdout);
136         line=fgets(line,sizeof(line),stdin);
137 #endif /* HAVE_LIBREADLINE */
138         if (!line)
139                 return NULL;
140 #ifndef HAVE_LIBREADLINE
141         if (line && (s=strchr(line,'\n')))
142                 *s='\0';
143 #endif /* HAVE_LIBREADLINE */
144
145         return line;
146 }
147
148 /* FIXME: HACK: Encode module essentiality to '.captivemodid.xml'. */
149 struct print_modules_available_foreach_param {
150         gboolean do_print;
151         gboolean ntoskrnl_exe_found;
152         gboolean ntfs_sys_found;
153         };
154
155 static void print_modules_available_foreach
156                 (const xmlChar *type /* key */,struct module_available *module_available /* value */,
157                 struct print_modules_available_foreach_param *param /* user_data */)
158 {
159         g_return_if_fail(type!=NULL);
160         g_return_if_fail(module_available!=NULL);
161         g_return_if_fail(module_available->module!=NULL);
162         g_return_if_fail(!strcmp(type,module_available->module->type));
163         g_return_if_fail(param!=NULL);
164
165         if (param->do_print)
166                 print_ui_line_module_available(module_available);
167
168         /**/ if (!strcmp(type,"ntoskrnl.exe"))
169                 param->ntoskrnl_exe_found=TRUE;
170         else if (!strcmp(type,"ntfs.sys"))
171                 param->ntfs_sys_found=TRUE;
172 }
173
174 /* Returns: TRUE if essential modules were found at any priority. */
175 static gboolean print_modules_available(void)
176 {
177 struct print_modules_available_foreach_param param;
178 gboolean r;
179 static gboolean first_time=TRUE;
180
181         putchar('\n');
182         param.do_print=!first_time;
183         param.ntoskrnl_exe_found=FALSE;
184         param.ntfs_sys_found=FALSE;
185         if (module_available_hash)
186                 g_hash_table_foreach(module_available_hash,(GHFunc)print_modules_available_foreach,&param);
187         r=param.ntoskrnl_exe_found && param.ntfs_sys_found;
188
189         if (!param.ntoskrnl_exe_found)
190                 printf(_("Still needed essential module: %s\n"),"ntoskrnl.exe");
191         if (!param.ntfs_sys_found)
192                 printf(_("Still needed essential module: %s\n"),"ntfs.sys");
193         if (r)
194                 puts(_(
195                                 "Essential modules (\"ntoskrnl.exe\" and \"ntfs.sys\") are available.\n"
196                                 "You may still want to get their better version and/or more modules."));
197         putchar('\n');
198
199         first_time=FALSE;
200
201         return r;
202 }
203
204 static gboolean ui_line_interactive_ask(const gchar *prompt)
205 {
206 char *line;
207 gboolean essentials_available;
208
209         if (all_modules_found)
210                 return FALSE;
211
212   essentials_available=print_modules_available();
213         puts(prompt);
214         for (;;) {
215                 line=line_read(captive_printf_alloca(_("Enter 'y' for YES, 'n' to NO%s [hit ENTER for YES]: "),
216                                 (!essentials_available ? "" : _(", 'd' if DONE"))));
217                 if (!line)
218                         return FALSE;
219                 if (!strncasecmp(line,_("yes"),strlen(line))) {
220                         free(line);
221                         return TRUE;
222                         }
223                 if (!strncasecmp(line,_("no"),strlen(line))) {
224                         free(line);
225                         return FALSE;
226                         }
227                 if (!strncasecmp(line,_("done"),strlen(line))) {
228                         putchar('\n');
229                         puts(final_text(all_modules_found));
230                         exit(EXIT_SUCCESS);
231                         }
232                 free(line);
233                 }
234         /* NOTREACHED */
235 }
236
237 static void ui_line_interactive(void)
238 {
239 #ifndef HAVE_LIBREADLINE
240         puts(_("Line editing not available, please recompile with readline library installed"));
241 #endif /* HAVE_LIBREADLINE */
242
243         if (ui_line_interactive_ask(_("Quickly scan your local disks to find needed drivers?")))
244                 scan_disks_quick();
245         while (!all_modules_found) {
246 char *line;
247
248                 if (ui_line_interactive_ask(_("Fully scan all directories of your local disks?")))
249                         scan_disks();
250
251                 if (!all_modules_found)
252                         do {
253                                 print_modules_available();
254                                 puts(_("Do you want to enter your custom search path and/or files? You can also enter web URL."));
255                                 line=line_read(_("Enter pathname or URL [hit ENTER to skip it]: "));
256                                 if (line && *line) {
257 GnomeVFSURI *uri;
258
259                                         uri=gnome_vfs_uri_new((strncmp(line,"http://",strlen("http://")) ? line
260                                                         : captive_printf_alloca("httpcaptive://%s",line+strlen("http://"))));
261                                         if (!uri)
262                                                 printf(_("Error paring URI: %s"),line);
263                                         else {
264                                                 mod_uri_load_base_reporting(uri);
265                                                 gnome_vfs_uri_unref(uri);
266                                                 }
267                                         free(line);
268                                         }
269                                 else {
270                                         free(line);
271                                         line=NULL;
272                                         }
273                                 } while (!all_modules_found && line);
274
275                 if (ui_line_interactive_ask(_(
276                                 "You can download the best available version of needed drivers from Microsoft. They can be found in Microsoft Windows XP Service Pack 1 Checked Build.\n"
277                                 "URL: http://www.microsoft.com/WindowsXP/pro/downloads/servicepacks/sp1/checkedbuild.asp\n"
278                                 "Legal: In some countries you need to have valid Microsoft Windows XP license to use it.\n"
279                                 "It is needed to download approx 29MB of data right now out of the 144MB file size. You can also download the file separately and load it in the previous screen if some problems occur.\n")))
280                         microsoft_com();
281                 if (!all_modules_found)
282                         puts(_("\nWe tried all available drivers acquiration methods - the options will start again."));
283                 }
284         putchar('\n');
285         puts(final_text(all_modules_found));
286 }
287
288 gboolean ui_line_init(void)
289 {
290         acquire_module_available_notify=ui_line_module_available_notify;
291         acquire_module_all_modules_found_notify=ui_line_all_modules_found_notify;
292         ui_progress=ui_line_progress;
293         ui_interactive=ui_line_interactive;
294         /* 'captivemodid_module_best_priority_notify' left NULL. */
295         return TRUE;
296 }