Implemented captive-install-acquire Gnome interface.
[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(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.\n"
277                                 "They can be found in Microsoft Windows XP Service Pack 1 Checked Build.\n"
278                                 "URL: http://www.microsoft.com/WindowsXP/pro/downloads/servicepacks/sp1/checkedbuild.asp\n"
279                                 "Legal: In some countries you need to have valid Microsoft Windows XP license to use it.\n"
280                                 "We will need to download approx 29MB od data right now (takes 2 hours on 33.6 modem).")))
281                         microsoft_com();
282                 if (!all_modules_found)
283                         puts(_("\nWe tried all available drivers acquiration method - the options will start again."));
284                 }
285         putchar('\n');
286         puts(final_text(all_modules_found));
287 }
288
289 gboolean ui_line_init(void)
290 {
291         acquire_module_available_notify=ui_line_module_available_notify;
292         acquire_module_all_modules_found_notify=ui_line_all_modules_found_notify;
293         ui_progress=ui_line_progress;
294         ui_interactive=ui_line_interactive;
295         /* 'captivemodid_module_best_priority_notify' left NULL. */
296         return TRUE;
297 }