diskscan.h \
main.c \
main.h \
+ microsoftcom.c \
+ microsoftcom.h \
moduriload.c \
- moduriload.h
+ moduriload.h \
+ ui-line.c \
+ ui-line.h
captive_install_acquire_CFLAGS=$(GNOME_VFS_CFLAGS) $(LIBXML_CFLAGS) $(OPENSSL_CFLAGS)
captive_install_acquire_LDADD =$(GNOME_VFS_LIBS) $(LIBXML_LIBS) $(OPENSSL_LIBS) $(LIBNTFS_LIBS) $(POPT_LIBS)
+captive_install_acquire_LDADD+= $(READLINE_LIBS) $(INTLLIBS)
+captive_install_acquire_LDFLAGS=$(READLINE_LDFLAGS)
captive_install_acquire_CFLAGS+=-DSYSCONFDIR="$(sysconfdir)"
+captive_install_acquire_CFLAGS+=-DVARLIBCAPTIVEDIR="$(localstatedir)/lib/$(PACKAGE)"
captive_install_acquire_LDADD+=../libcaptive-install/libcaptive-install.a
EXTRA_DIST+= \
#include "moduriload.h"
#include <sys/mman.h>
#include <unistd.h>
+#include "main.h"
#include <captive/macros.h>
{
g_return_if_fail(acquire_cabinet!=NULL);
+ (*ui_search_is_aborted)();
+
acquire_cabinet->offset=offset;
}
{
g_return_if_fail(acquire_cabinet!=NULL);
+ (*ui_search_is_aborted)();
+
acquire_cabinet->offset+=offset;
}
{
g_return_val_if_fail(acquire_cabinet!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
+ (*ui_search_is_aborted)();
+
return acquire_cabinet->offset;
}
g_return_val_if_fail(acquire_cabinet!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
g_return_val_if_fail(buffer!=NULL || bytes==0,GNOME_VFS_ERROR_BAD_PARAMETERS);
+ if ((*ui_search_is_aborted)())
+ return GNOME_VFS_ERROR_INTERRUPTED;
+
bytes=MAX(0,MIN(bytes,acquire_cabinet->size-acquire_cabinet->offset));
if (!bytes)
return GNOME_VFS_ERROR_EOF;
g_return_val_if_fail(fi==file_write_fi_assertion,0);
g_return_val_if_fail(file_write_bytearray!=NULL,0);
+ if ((*ui_search_is_aborted)())
+ return 0;
+
g_byte_array_append(file_write_bytearray,buf,length);
return 1; /* success */
g_return_if_fail(acquire_cabinet!=NULL);
+ if ((*ui_search_is_aborted)())
+ return;
+
basecab=find_cabs_in_file(acquire_cabinet);
if (!basecab)
return;
if (!captivemodid_module_length_is_valid(fi->length))
continue;
+ if ((*ui_search_is_aborted)())
+ return;
+
file_write_fi_assertion=fi;
file_write_bytearray=g_byte_array_new();
extract_file(fi,
module_md5_hash=g_hash_table_new(g_str_hash,g_str_equal);
}
+/* map: (const xmlChar *)type -> (gpointer)GINT_TO_POINTER(priority) */
+/* We remove entry for module with already the best priority found,
+ * therefore captivemodid_module_type_best_priority_lookup() will return
+ * 'G_MININT' afterwards.
+ */
+static GHashTable *module_type_best_priority_hash;
+
+static void module_type_best_priority_hash_init(void)
+{
+ if (module_type_best_priority_hash)
+ return;
+ module_type_best_priority_hash=g_hash_table_new(g_str_hash,g_str_equal);
+}
+
static void captivemodid_load_module(struct captivemodid_module *module)
{
struct captivemodid_module *module_md5_conflict;
return;
}
g_hash_table_insert(module_md5_hash,(/* de-const */ xmlChar *)module->md5,module);
+
module_valid_length_hash_init();
g_hash_table_insert(module_valid_length_hash,GINT_TO_POINTER(module->length),module_valid_length_hash);
+
+ if (strcmp(module->type,"cabinet")) {
+ if (module->priority>captivemodid_module_type_best_priority_lookup(module->type)) {
+ module_type_best_priority_hash_init();
+ g_hash_table_insert(module_type_best_priority_hash,
+ (/* de-const */ xmlChar *)module->type,GINT_TO_POINTER(module->priority));
+ }
+ }
}
gboolean captivemodid_module_length_is_valid(GnomeVFSFileSize file_size)
if ((GnomeVFSFileSize)(file_size_gint=file_size)!=file_size) /* Size too big to be valid. */
return FALSE;
+ module_valid_length_hash_init();
return !!g_hash_table_lookup(module_valid_length_hash,GINT_TO_POINTER(file_size_gint));
}
{
g_return_val_if_fail(file_md5!=NULL,NULL);
+ module_md5_hash_init();
return g_hash_table_lookup(module_md5_hash,file_md5);
}
+gint captivemodid_module_type_best_priority_lookup(const xmlChar *module_type)
+{
+gpointer r_gpointer;
+gboolean errbool;
+
+ g_return_val_if_fail(module_type!=NULL,G_MININT);
+
+ module_type_best_priority_hash_init();
+ errbool=g_hash_table_lookup_extended(module_type_best_priority_hash,
+ module_type, /* lookup_key */
+ NULL, /* orig_key */
+ &r_gpointer); /* value */
+ if (!errbool)
+ return G_MININT;
+
+ return GPOINTER_TO_INT(r_gpointer);
+}
+
+/* Returns: TRUE if all modules were found. */
+gboolean captivemodid_module_type_best_priority_found(const xmlChar *module_type)
+{
+gboolean errbool;
+
+ g_return_val_if_fail(module_type!=NULL,FALSE);
+
+ module_type_best_priority_hash_init();
+ errbool=g_hash_table_remove(module_type_best_priority_hash,module_type);
+ g_assert(errbool==TRUE);
+
+ return !g_hash_table_size(module_type_best_priority_hash);
+}
+
static xmlChar *captivemodid_load_module_xml_get_attr
(const gchar *captivemodid_pathname,xmlTextReader *xml_reader,const gchar *attr_name)
{
}
-void captivemodid_load(const gchar *captivemodid_pathname)
+gboolean captivemodid_load(const gchar *captivemodid_pathname)
{
xmlTextReader *xml_reader;
- xml_reader=xmlNewTextReaderFilename(captivemodid_pathname);
- g_assert(xml_reader!=NULL);
+ if (!(xml_reader=xmlNewTextReaderFilename(captivemodid_pathname)))
+ return FALSE;
while (1==xmlTextReaderRead(xml_reader)) {
switch (xmlTextReaderNodeType(xml_reader)) {
}
}
xmlFreeTextReader(xml_reader);
+ return TRUE;
}
gchar *calc_md5(gconstpointer base,size_t length);
gboolean captivemodid_module_length_is_valid(GnomeVFSFileSize file_size);
struct captivemodid_module *captivemodid_module_md5_lookup(const gchar *file_md5);
-void captivemodid_load(const gchar *captivemodid_pathname);
+gint captivemodid_module_type_best_priority_lookup(const xmlChar *module_type);
+gboolean captivemodid_module_type_best_priority_found(const xmlChar *module_type);
+gboolean captivemodid_load(const gchar *captivemodid_pathname);
G_END_DECLS
#include <errno.h>
#include <unistd.h>
#include <libgnomevfs/gnome-vfs-init.h>
+#include "ui-line.h"
+#include "microsoftcom.h"
#include <captive/macros.h>
int optarg_verbose;
+int optarg_dry;
+static int optarg_microsoft_com;
static int optarg_scan_disks;
+static int optarg_scan_disks_quick;
+static char *optarg_modid_path=G_STRINGIFY(SYSCONFDIR) "/w32-mod-id.captivemodid.xml";
static GList *optarg_scan_path_list; /* of (char *) */
static void acquire_popt_callback
argDescrip: (argDescripP), \
}
- BUG_ACQUIRE_POPT('v',"verbose" ,POPT_ARG_NONE ,&optarg_verbose ,0,N_("Display additional debug information"),NULL),
- BUG_ACQUIRE_POPT(0 ,"scan-disks",POPT_ARG_NONE ,&optarg_scan_disks,0,N_("Scan all local disks"),NULL),
- BUG_ACQUIRE_POPT(0 ,"scan-path" ,POPT_ARG_STRING,NULL ,0,N_("Scan specified disk path"),N_("path/URI")),
+ BUG_ACQUIRE_POPT('v',"verbose" ,POPT_ARG_NONE ,&optarg_verbose,0,N_("Display additional debug information"),NULL),
+ BUG_ACQUIRE_POPT('n',"dry" ,POPT_ARG_NONE ,&optarg_dry ,0,N_("No modifications, no files written"),NULL),
+ BUG_ACQUIRE_POPT(0 ,"modid-path" ,POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,&optarg_modid_path,0,
+ N_("Path to .captivemodid.xml database"),N_("path")),
+ BUG_ACQUIRE_POPT(0 ,"scan-disks" ,POPT_ARG_NONE ,&optarg_scan_disks,0,N_("Scan all files on local disks"),NULL),
+ BUG_ACQUIRE_POPT(0 ,"scan-disks-quick",POPT_ARG_NONE ,&optarg_scan_disks_quick,0,
+ N_("Scan MS-Windows directories on local disks"),NULL),
+ BUG_ACQUIRE_POPT(0 ,"scan-path" ,POPT_ARG_STRING,NULL ,0,
+ N_("Scan specified disk path or web URL"),N_("path/URI")),
+ BUG_ACQUIRE_POPT(0 ,"microsoft-com" ,POPT_ARG_NONE ,&optarg_microsoft_com,0,
+ N_("Download from microsoft.com; Legal: You may need to have valid Microsoft Windows XP license."),NULL),
#undef BUG_ACQUIRE_POPT
POPT_AUTOHELP
}
+void (*ui_interactive)(void);
+
+static gboolean ui_search_is_aborted_dummy(void)
+{
+ return FALSE; /* not aborted */
+}
+
+gboolean (*ui_search_is_aborted)(void)=ui_search_is_aborted_dummy;
+
+static GList *mod_uri_list_local;
+static void mod_uri_list_local_init(void)
+{
+ if (mod_uri_list_local)
+ return;
+ mod_uri_list_local=mod_uri_list();
+}
+
+void scan_disks_quick(void)
+{
+GList *mod_uri_list_quick_local,*mod_uri_l;
+
+ mod_uri_list_local_init();
+ mod_uri_list_quick_local=NULL;
+ for (mod_uri_l=mod_uri_list_local;mod_uri_l;mod_uri_l=mod_uri_l->next) {
+ mod_uri_list_quick_local=g_list_prepend(mod_uri_list_quick_local,
+ gnome_vfs_uri_append_path(mod_uri_l->data,"windows/system32"));
+ }
+ mod_uri_list_quick_local=g_list_reverse(mod_uri_list_quick_local);
+ g_list_foreach(mod_uri_list_quick_local,(GFunc)mod_uri_load,NULL);
+ gnome_vfs_uri_list_free(mod_uri_list_quick_local);
+}
+
+void scan_disks(void)
+{
+ mod_uri_list_local_init();
+ g_list_foreach(mod_uri_list_local,(GFunc)mod_uri_load,NULL);
+}
+
+void microsoft_com(void)
+{
+ g_list_foreach(mod_uri_microsoftcom_list(),(GFunc)mod_uri_load,NULL);
+}
+
+static void scan_batch(void)
+{
+ g_list_foreach(optarg_scan_path_list,(GFunc)mod_uri_load,NULL);
+
+ if (optarg_scan_disks_quick)
+ scan_disks_quick();
+ if (optarg_scan_disks)
+ scan_disks();
+ if (optarg_microsoft_com)
+ microsoft_com();
+}
+
int main(int argc,char **argv)
{
poptContext context;
int errint;
-GList *scan_uri_list;
+gboolean is_interactive;
-#ifdef MAINTAINER_MODE
+#if 0
g_log_set_always_fatal(~(0
|G_LOG_LEVEL_MESSAGE
|G_LOG_LEVEL_INFO
return EXIT_FAILURE;
}
- scan_uri_list=NULL;
- scan_uri_list=g_list_concat(scan_uri_list,gnome_vfs_uri_list_copy(optarg_scan_path_list));
- if (optarg_scan_disks)
- scan_uri_list=g_list_concat(scan_uri_list,mod_uri_list());
+ is_interactive=(1
+ && ! optarg_scan_path_list
+ && ! optarg_scan_disks_quick
+ && ! optarg_scan_disks
+ && ! optarg_microsoft_com);
+
+ /* Initialize UI here to catch all GLog errors below. */
+ if (!ui_line_init())
+ g_error(_("No UI interface could be initialized"));
- captivemodid_load("./w32-mod-id.captivemodid.xml");
- g_list_foreach(scan_uri_list,(GFunc)mod_uri_load,NULL);
+ if (!captivemodid_load(optarg_modid_path) && !captivemodid_load("./w32-mod-id.captivemodid.xml"))
+ g_error(_("Unable to load modid database: %s"),optarg_modid_path);
+
+{
+void (*acquire_module_available_notify_orig)(struct module_available *module_available);
+void (*acquire_module_all_modules_found_notify_orig)(void);
+
+ acquire_module_available_notify_orig=acquire_module_available_notify;
+ acquire_module_available_notify=NULL;
+ acquire_module_all_modules_found_notify_orig=acquire_module_all_modules_found_notify;
+ acquire_module_all_modules_found_notify=NULL;
+ mod_uri_load(gnome_vfs_uri_new("file://" G_STRINGIFY(VARLIBCAPTIVEDIR)));
+ acquire_module_available_notify=acquire_module_available_notify_orig;
+ acquire_module_all_modules_found_notify=acquire_module_all_modules_found_notify_orig;
+ }
+
+ if (!is_interactive)
+ scan_batch();
+ else if (!(*ui_search_is_aborted)()) {
+ (*ui_interactive)();
+ }
gnome_vfs_shutdown();
G_BEGIN_DECLS
extern gboolean optarg_verbose;
+extern gboolean optarg_dry;
+extern void (*ui_interactive)(void);
+extern gboolean (*ui_search_is_aborted)(void);
+
+void scan_disks_quick(void);
+void scan_disks(void);
+void microsoft_com(void);
G_END_DECLS
--- /dev/null
+/* $Id$
+ * W32 modules finder from microsoft.com Internet download
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "config.h"
+
+#include "microsoftcom.h" /* self */
+#include <glib/gmessages.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <libgnomevfs/gnome-vfs-result.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <string.h>
+
+#include <captive/macros.h>
+
+
+/* Config: */
+/* Do we really need to use indirection by the following 'base' URL?
+ * It appears to me as if some Microsoft Service Pack files URLs
+ * have changed in the past.
+ */
+#define MICROSOFTCOM_URL "http://www.microsoft.com/WindowsXP/pro/downloads/servicepacks/sp1/checkedbuild.asp"
+
+
+GList * /* of (GnomeVFSURI *) */ mod_uri_microsoftcom_list(void)
+{
+int base_size;
+char *base_contents;
+char *href,*href_end;
+const char *href2;
+GnomeVFSURI *uri;
+
+ base_contents=NULL;
+ if (GNOME_VFS_OK!=gnome_vfs_read_entire_file(MICROSOFTCOM_URL,&base_size,&base_contents)
+ || base_size<=0) {
+ g_warning(_("Cannot load file-URL pointing base URL: %s"),MICROSOFTCOM_URL);
+ goto fail_free_base_contents;
+ }
+ base_contents[base_size-1]=0; /* string terminator */
+ if (!(href=strstr(base_contents,"http://download.microsoft.com/")) || !(href_end=strchr(href,'"'))) {
+ g_warning(_("File-URL not found in base URL: %s"),MICROSOFTCOM_URL);
+ goto fail_free_base_contents;
+ }
+ *href_end=0;
+ if (strncmp(href,"http://",strlen("http://"))) {
+ g_warning(_("File URL not valid: %s"),href);
+ goto fail_free_base_contents;
+ }
+ href2=captive_printf_alloca("httpcaptive://%s",href+strlen("http://"));
+ if (!(uri=gnome_vfs_uri_new(href2))) {
+ g_warning(_("Found file URL not parsable: %s"),href2);
+ goto fail_free_base_contents;
+ }
+ g_free(base_contents);
+ return g_list_append(NULL,uri);
+
+fail_free_base_contents:
+ g_free(base_contents);
+ return NULL;
+}
--- /dev/null
+/* $Id$
+ * Include file for W32 modules finder from microsoft.com Internet download
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _CAPTIVE_INSTALL_ACQUIRE_MICROSOFTCOM_H
+#define _CAPTIVE_INSTALL_ACQUIRE_MICROSOFTCOM_H 1
+
+
+#include <glib/gtypes.h>
+#include <glib/glist.h>
+
+
+G_BEGIN_DECLS
+
+GList * /* of (GnomeVFSURI *) */ mod_uri_microsoftcom_list(void);
+
+G_END_DECLS
+
+
+#endif /* _CAPTIVE_INSTALL_ACQUIRE_MICROSOFTCOM_H */
#include "cabinet.h"
#include <libgnomevfs/gnome-vfs-ops.h>
#include <libgnomevfs/gnome-vfs-directory.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <captive/macros.h>
/* Config: */
#define MAX_FILE_LOAD_LENGTH 5000000 /* Otherwise use cabextract-over-http. */
+/* map: (const xmlChar *)type -> (struct module_available *) */
+GHashTable *module_available_hash;
+
+static void module_available_hash_value_destroy_func(struct module_available *module_available)
+{
+ g_return_if_fail(module_available!=NULL);
+
+ g_free(module_available->file_base);
+ g_free(module_available->uri_text);
+ g_free(module_available);
+}
+
+static void module_available_hash_init(void)
+{
+ if (module_available_hash)
+ return;
+ module_available_hash=g_hash_table_new_full(g_str_hash,g_str_equal,
+ (GDestroyNotify)NULL,
+ (GDestroyNotify)module_available_hash_value_destroy_func);
+}
+
+
+void (*acquire_module_available_notify)(struct module_available *module_available);
+void (*acquire_module_all_modules_found_notify)(void);
+
static void mod_uri_load_module_from_memory
(struct captivemodid_module *module,gconstpointer file_base,size_t file_length,GnomeVFSURI *uri)
{
-gchar *uri_text;
+struct module_available *module_available;
+gint best_priority;
+gboolean all_modules_found;
g_return_if_fail(module!=NULL);
g_return_if_fail(file_base!=NULL);
g_return_if_fail(uri!=NULL);
+ g_return_if_fail((size_t)module->length==file_length);
+
+ module_available_hash_init();
+ if ((module_available=g_hash_table_lookup(module_available_hash,module->type))) {
+ if (module_available->module->priority>=module->priority)
+ return;
+ }
+
+ captive_new(module_available);
+ module_available->module=module;
+ module_available->file_base=g_memdup(file_base,file_length);
+ module_available->uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
+ /* It may possibly destroy the old 'module_available': */
+ g_hash_table_insert(module_available_hash,(/* de-const */ xmlChar *)module->type,module_available);
+
+ if (!optarg_dry) {
+const gchar *dest_pathname;
+int dest_fd;
+
+ dest_pathname=captive_printf_alloca("%s/%s",G_STRINGIFY(VARLIBCAPTIVEDIR),module->type);
+ if (-1==(dest_fd=open(dest_pathname,O_CREAT|O_TRUNC|O_WRONLY,0644)))
+ g_warning(_("Cannot open target file \"%s\": %m"),dest_pathname);
+ else {
+ if ((ssize_t)file_length!=write(dest_fd,file_base,file_length))
+ g_warning(_("Error writing target file \"%s\": %m"),dest_pathname);
+ if (close(dest_fd))
+ g_warning(_("Error closing target file \"%s\": %m"),dest_pathname);
+ }
+ }
- uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
- g_message("type=%s,id:%s: %s",module->type,module->id,uri_text);
- g_free(uri_text);
+ all_modules_found=FALSE;
+
+ best_priority=captivemodid_module_type_best_priority_lookup(module->type);
+ if (best_priority==G_MININT /* no longer seeking for such module */
+ || module_available->module->priority==best_priority) {
+ if (captivemodid_module_type_best_priority_found(module->type)) {
+ /* Postpone (*acquire_module_all_modules_found_notify)()
+ * after (*acquire_module_available_notify)().
+ */
+ all_modules_found=TRUE;
+ }
+ }
+
+ if (acquire_module_available_notify)
+ (*acquire_module_available_notify)(module_available);
+ if (all_modules_found)
+ if (acquire_module_all_modules_found_notify)
+ (*acquire_module_all_modules_found_notify)();
}
void mod_uri_load_file_from_memory(gconstpointer file_base,size_t file_length,GnomeVFSURI *uri)
*recurse=FALSE;
+ if ((*ui_search_is_aborted)())
+ return FALSE; /* abort traversal */
+
switch (info->type) {
case GNOME_VFS_FILE_TYPE_REGULAR: {
GnomeVFSURI *file_uri;
G_BEGIN_DECLS
+struct module_available {
+ struct captivemodid_module *module;
+ gpointer file_base; /* of 'module->length' */
+ gchar *uri_text;
+ };
+
+/* map: (const xmlChar *)type -> (struct module_available *) */
+extern GHashTable *module_available_hash;
+
+extern void (*acquire_module_available_notify)(struct module_available *module_available);
+extern void (*acquire_module_all_modules_found_notify)(void);
+
void mod_uri_load_file_from_memory(gconstpointer file_base,size_t file_length,GnomeVFSURI *uri);
void mod_uri_load(GnomeVFSURI *uri);
--- /dev/null
+/* $Id$
+ * Drivers acquiring installation utility
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "config.h"
+
+#include "ui-line.h" /* self */
+#include <glib/gmessages.h>
+#include "moduriload.h"
+#include "main.h"
+#include <unistd.h>
+#include <time.h>
+
+#ifdef HAVE_LIBREADLINE
+#include <readline/readline.h>
+#ifdef HAVE_READLINE_HISTORY_H
+#include <readline/history.h>
+#endif /* HAVE_READLINE_HISTORY_H */
+#endif /* HAVE_LIBREADLINE */
+
+#include <captive/macros.h>
+
+static void print_ui_line_module_available(struct module_available *module_available)
+{
+gint priority_best;
+
+ g_return_if_fail(module_available!=NULL);
+ g_return_if_fail(module_available->module!=NULL);
+
+ if (G_MININT==(priority_best=captivemodid_module_type_best_priority_lookup(module_available->module->type)))
+ printf(_("Found best available \"%s\": %s\n"),module_available->module->type,module_available->module->id);
+ else
+ printf(_("Found although not best \"%s\" (pri=%d; best=%d): %s\n"),
+ module_available->module->type,module_available->module->priority,priority_best,
+ module_available->module->id);
+}
+
+static void ui_line_module_available_notify(struct module_available *module_available)
+{
+ g_return_if_fail(module_available!=NULL);
+
+ print_ui_line_module_available(module_available);
+ printf(_("at URI: %s\n"),module_available->uri_text);
+}
+
+static gboolean all_modules_found=FALSE;
+
+static void ui_line_all_modules_found_notify(void)
+{
+ puts(_("All modules found in their best known versions."));
+ all_modules_found=TRUE;
+}
+
+static gboolean aborted=FALSE;
+static time_t search_start_time;
+static gboolean abort_msg_printed=FALSE;
+
+static gboolean ui_line_search_is_aborted(void)
+{
+fd_set readfds;
+struct timeval timeval;
+
+ if (aborted)
+ return TRUE;
+ if (all_modules_found)
+ return TRUE;
+
+ if (!search_start_time)
+ search_start_time=time(NULL);
+ if (!abort_msg_printed && time(NULL)>=search_start_time+2) {
+ puts(_("Searching... Hit ENTER to abort."));
+ abort_msg_printed=TRUE;
+ }
+
+ if (isatty(0)) {
+ FD_ZERO(&readfds);
+ FD_SET(0,&readfds);
+ timeval.tv_sec=0;
+ timeval.tv_usec=0;
+ if (1==select(1,&readfds,NULL,NULL,&timeval)) {
+ aborted=TRUE;
+ getchar();
+ puts(_("*** OPERATION ABORTED ***"));
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void ui_line_search_is_aborted_reset(void)
+{
+ aborted=FALSE;
+ search_start_time=0;
+ abort_msg_printed=FALSE;
+}
+
+static char *line_read(const gchar *prompt)
+{
+#ifdef HAVE_LIBREADLINE
+char *line;
+#else /* HAVE_LIBREADLINE */
+char line[1024],*s;
+#endif /* HAVE_LIBREADLINE */
+
+ g_return_val_if_fail(prompt!=NULL,NULL);
+
+ ui_line_search_is_aborted_reset();
+
+#ifdef HAVE_LIBREADLINE
+ line=readline(prompt);
+#ifdef HAVE_ADD_HISTORY
+ if (line && *line)
+ add_history(line);
+#endif /* HAVE_ADD_HISTORY */
+#else /* HAVE_LIBREADLINE */
+ fputs(prompt,stdout); fflush(stdout);
+ line=fgets(line,sizeof(line),stdin);
+#endif /* HAVE_LIBREADLINE */
+ if (!line)
+ return NULL;
+#ifndef HAVE_LIBREADLINE
+ if (line && (s=strchr(line,'\n')))
+ *s='\0';
+#endif /* HAVE_LIBREADLINE */
+
+ return line;
+}
+
+/* FIXME: HACK: Encode module essentiality to '.captivemodid.xml'. */
+struct print_modules_available_foreach_param {
+ gboolean ntoskrnl_exe_found;
+ gboolean ntfs_sys_found;
+ };
+
+static void print_modules_available_foreach
+ (const xmlChar *type /* key */,struct module_available *module_available /* value */,
+ struct print_modules_available_foreach_param *param /* user_data */)
+{
+ g_return_if_fail(type!=NULL);
+ g_return_if_fail(module_available!=NULL);
+ g_return_if_fail(module_available->module!=NULL);
+ g_return_if_fail(!strcmp(type,module_available->module->type));
+ g_return_if_fail(param!=NULL);
+
+ print_ui_line_module_available(module_available);
+
+ /**/ if (!strcmp(type,"ntoskrnl.exe"))
+ param->ntoskrnl_exe_found=TRUE;
+ else if (!strcmp(type,"ntfs.sys"))
+ param->ntfs_sys_found=TRUE;
+}
+
+/* Returns: TRUE if essential modules were found at any priority. */
+static gboolean print_modules_available(void)
+{
+struct print_modules_available_foreach_param param;
+gboolean r;
+
+ putchar('\n');
+ param.ntoskrnl_exe_found=FALSE;
+ param.ntfs_sys_found=FALSE;
+ if (module_available_hash)
+ g_hash_table_foreach(module_available_hash,(GHFunc)print_modules_available_foreach,¶m);
+ r=param.ntoskrnl_exe_found && param.ntfs_sys_found;
+
+ if (!param.ntoskrnl_exe_found)
+ printf(_("Still needed essential module: %s\n"),"ntoskrnl.exe");
+ if (!param.ntfs_sys_found)
+ printf(_("Still needed essential module: %s\n"),"ntfs.sys");
+ if (r)
+ puts(_(
+ "Essential modules (\"ntoskrnl.exe\" and \"ntfs.sys\") are available.\n"
+ "You still may want to get their better version and/or more modules."));
+ putchar('\n');
+
+ return r;
+}
+
+static gboolean ui_line_interactive_ask(const gchar *prompt)
+{
+char *line;
+gboolean essentials_available;
+
+ if (all_modules_found)
+ return FALSE;
+
+ essentials_available=print_modules_available();
+ puts(prompt);
+ for (;;) {
+ line=line_read(captive_printf_alloca(_("Enter 'y' for YES, 'n' to NO%s [hit ENTER for YES]: "),
+ (!essentials_available ? "" : _(", 'd' if DONE"))));
+ if (!line)
+ return FALSE;
+ if (!strncasecmp(line,_("yes"),strlen(line))) {
+ free(line);
+ return TRUE;
+ }
+ if (!strncasecmp(line,_("no"),strlen(line))) {
+ free(line);
+ return FALSE;
+ }
+ if (!strncasecmp(line,_("done"),strlen(line)))
+ exit(EXIT_SUCCESS);
+ free(line);
+ }
+ /* NOTREACHED */
+}
+
+static void ui_line_interactive(void)
+{
+#ifndef HAVE_LIBREADLINE
+ puts(_("Line editing not available, please recompile with readline library installed"));
+#endif /* HAVE_LIBREADLINE */
+
+ if (ui_line_interactive_ask(_("Quickly scan your local disks to find needed drivers?")))
+ scan_disks_quick();
+ while (!all_modules_found) {
+char *line;
+
+ if (ui_line_interactive_ask(_("Fully scan all directories of your local disks?")))
+ scan_disks();
+
+ if (!all_modules_found)
+ do {
+ print_modules_available();
+ puts(_("Do you want to enter your custom search path and/or files? You can also enter web URL."));
+ line=line_read(_("Enter pathname or URL [hit ENTER to skip it]: "));
+ if (line && *line) {
+GnomeVFSURI *uri;
+
+ uri=gnome_vfs_uri_new((strncmp(line,"http://",strlen("http://")) ? line
+ : captive_printf_alloca("httpcaptive://%s",line+strlen("http://"))));
+ if (!uri)
+ printf(_("Error paring URI: %s"),line);
+ else {
+ mod_uri_load(uri);
+ gnome_vfs_uri_unref(uri);
+ }
+ free(line);
+ }
+ else {
+ free(line);
+ line=NULL;
+ }
+ } while (!all_modules_found && line);
+
+ if (ui_line_interactive_ask(_(
+ "You can download the best available version of needed drivers from Microsoft.\n"
+ "They can be found in Microsoft Windows XP Service Pack 1 Checked Build.\n"
+ "URL: http://www.microsoft.com/WindowsXP/pro/downloads/servicepacks/sp1/checkedbuild.asp\n"
+ "Legal: In some countries you need to have valid Microsoft Windows XP license to use it.\n"
+ "We will need to download approx 29MB od data right now (takes 2 hours on 33.6 modem).")))
+ microsoft_com();
+ if (!all_modules_found)
+ puts(_("\nWe tried all available drivers acquiration method - the options will start again."));
+ }
+}
+
+gboolean ui_line_init(void)
+{
+ acquire_module_available_notify=ui_line_module_available_notify;
+ acquire_module_all_modules_found_notify=ui_line_all_modules_found_notify;
+ ui_search_is_aborted=ui_line_search_is_aborted;
+ ui_interactive=ui_line_interactive;
+ return TRUE;
+}
--- /dev/null
+/* $Id$
+ * Include file for drivers acquiring installation utility
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _CAPTIVE_INSTALL_ACQUIRE_UI_LINE_H
+#define _CAPTIVE_INSTALL_ACQUIRE_UI_LINE_H 1
+
+
+#include <glib/gtypes.h>
+
+
+G_BEGIN_DECLS
+
+gboolean ui_line_init(void);
+
+G_END_DECLS
+
+
+#endif /* _CAPTIVE_INSTALL_ACQUIRE_UI_LINE_H */