X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=blobdiff_plain;f=src%2Finstaller%2Fmain.c;h=d02db2834afeccb60c891d88964640c6edf44000;hp=5a2e0c40670dad1f083cdffccad92214e525c5e2;hb=ade96ba8a590df6411f7effec637609494072034;hpb=c0511f3ab35cc059e0777b7481eaee105c738f5e diff --git a/src/installer/main.c b/src/installer/main.c index 5a2e0c4067..d02db2834a 100644 --- a/src/installer/main.c +++ b/src/installer/main.c @@ -7,6 +7,7 @@ * Contains main entry point, and misc functions.6 * */ +#define _GNU_SOURCE #include #include @@ -24,7 +25,7 @@ #define INST_FILECOUNT 21000 #define LICENSE_FILE "/cdrom/COPYING" -#define SOURCE_TEMPFILE "/tmp/downloaded-image.iso" +#define SOURCE_TEMPFILE "/tmp/downloads/image.iso" extern char url[STRING_SIZE]; @@ -103,6 +104,37 @@ static int newtWinOkCancel(const char* title, const char* message, int width, in const char* btn_txt_ok, const char* btn_txt_cancel) { int ret = 1; + unsigned int btn_width_ok = strlen(btn_txt_ok); + unsigned int btn_width_cancel = strlen(btn_txt_cancel); + + // Maybe make the box wider to fix both buttons inside + unsigned int min_width = btn_width_ok + btn_width_cancel + 5; + if (width < min_width) + width = min_width; + + unsigned int btn_pos_ok = (width / 3) - (btn_width_ok / 2) - 1; + unsigned int btn_pos_cancel = (width * 2 / 3) - (btn_width_cancel / 2) - 1; + + // Move buttons a bit if they overlap + while ((btn_pos_ok + btn_width_ok + 5) > btn_pos_cancel) { + // Move the cancel button to the right if there is enough space left + if ((btn_pos_cancel + btn_width_cancel + 2) < width) { + ++btn_pos_cancel; + continue; + } + + // Move the OK button to the left if possible + if (btn_pos_ok > 1) { + --btn_pos_ok; + continue; + } + + // If they still overlap, we cannot fix the situtation + // and break. Should actually never get here, because we + // adjust the width of the window earlier. + break; + } + newtCenteredWindow(width, height, title); newtComponent form = newtForm(NULL, NULL, 0); @@ -111,12 +143,8 @@ static int newtWinOkCancel(const char* title, const char* message, int width, in newtTextboxSetText(textbox, message); newtFormAddComponent(form, textbox); - unsigned int btn_width_ok = strlen(btn_txt_ok); - unsigned int btn_width_cancel = strlen(btn_txt_cancel); - - newtComponent btn_ok = newtButton((width / 3) - (btn_width_ok / 2) - 2, height - 4, btn_txt_ok); - newtComponent btn_cancel = newtButton((width * 2 / 3) - (btn_width_cancel / 2) - 2, height - 4, - btn_txt_cancel); + newtComponent btn_ok = newtButton(btn_pos_ok, height - 4, btn_txt_ok); + newtComponent btn_cancel = newtButton(btn_pos_cancel, height - 4, btn_txt_cancel); newtFormAddComponents(form, btn_ok, btn_cancel, NULL); @@ -162,7 +190,7 @@ static int newtLicenseBox(const char* title, const char* text, int width, int he return ret; } -int write_lang_configs(const char *lang) { +int write_lang_configs(char* lang) { struct keyvalue *kv = initkeyvalues(); /* default stuff for main/settings. */ @@ -206,7 +234,7 @@ static char* center_string(const char* str, int width) { } #define DEFAULT_LANG "English" -#define NUM_LANGS 8 +#define NUM_LANGS 10 static struct lang { const char* code; @@ -230,13 +258,17 @@ static struct config { int serial_console; int require_networking; int perform_download; + int disable_swap; char download_url[STRING_SIZE]; + char postinstall[STRING_SIZE]; } config = { .unattended = 0, .serial_console = 0, .require_networking = 0, .perform_download = 0, + .disable_swap = 0, .download_url = DOWNLOAD_URL, + .postinstall = "\0", }; static void parse_command_line(struct config* c) { @@ -253,11 +285,11 @@ static void parse_command_line(struct config* c) { while (token) { strncpy(buffer, token, sizeof(buffer)); - char* val = &buffer; + char* val = buffer; char* key = strsep(&val, "="); // serial console - if (strcmp(token, "console=ttyS0") == 0) + if ((strcmp(key, "console") == 0) && (strncmp(val, "ttyS", 4) == 0)) c->serial_console = 1; // enable networking? @@ -268,11 +300,22 @@ static void parse_command_line(struct config* c) { else if (strcmp(token, "installer.unattended") == 0) c->unattended = 1; + // disable swap + else if (strcmp(token, "installer.disable-swap") == 0) + c->disable_swap = 1; + // download url else if (strcmp(key, "installer.download-url") == 0) { - strncpy(&c->download_url, val, sizeof(c->download_url)); + strncpy(c->download_url, val, sizeof(c->download_url)); c->perform_download = 1; + // Require networking for the download + c->require_networking = 1; + + // postinstall script + } else if (strcmp(key, "installer.postinstall") == 0) { + strncpy(c->postinstall, val, sizeof(c->postinstall)); + // Require networking for the download c->require_networking = 1; } @@ -301,11 +344,10 @@ int main(int argc, char *argv[]) { char message[STRING_SIZE]; char title[STRING_SIZE]; int allok = 0; - FILE *handle, *copying; - char line[STRING_SIZE]; - - setlocale (LC_ALL, ""); - sethostname( SNAME , 10); + FILE *copying; + + setlocale(LC_ALL, ""); + sethostname(SNAME, 10); /* Log file/terminal stuff. */ FILE* flog = NULL; @@ -364,13 +406,19 @@ int main(int argc, char *argv[]) { assert(choice <= NUM_LANGS); fprintf(flog, "Selected language: %s (%s)\n", languages[choice].name, languages[choice].code); - snprintf(language, sizeof(language), languages[choice].code); + snprintf(language, sizeof(language), "%s", languages[choice].code); setenv("LANGUAGE", language, 1); setlocale(LC_ALL, language); } - char* helpline = center_string(_("/ between elements | selects | next screen"), screen_cols); + // Set helpline + char* helpline = NULL; + if (config.unattended) + helpline = center_string(_("Unattended mode"), screen_cols); + else + helpline = center_string(_("/ between elements | selects | next screen"), screen_cols); + newtPushHelpLine(helpline); if (!config.unattended) { @@ -454,7 +502,7 @@ int main(int argc, char *argv[]) { FILE* f = fopen(SOURCE_TEMPFILE, "r"); if (f) { - sourcedrive = SOURCE_TEMPFILE; + sourcedrive = strdup(SOURCE_TEMPFILE); fclose(f); } else { char reason[STRING_SIZE] = "-"; @@ -487,7 +535,7 @@ int main(int argc, char *argv[]) { // Read the license file. if (!(copying = fopen(LICENSE_FILE, "r"))) { sprintf(discl_msg, "Could not open license file: %s\n", LICENSE_FILE); - fprintf(flog, discl_msg); + fprintf(flog, "%s", discl_msg); } else { fread(discl_msg, 1, 40000, copying); fclose(copying); @@ -510,7 +558,7 @@ int main(int argc, char *argv[]) { // Check how many disks have been found and what // we can do with them. - unsigned int num_disks = hw_count_disks(disks); + unsigned int num_disks = hw_count_disks((const struct hw_disk**)disks); while (1) { // no harddisks found @@ -522,7 +570,7 @@ int main(int argc, char *argv[]) { // or if we are running in unattended mode, we will select // the first disk and go with that one } else if ((num_disks == 1) || (config.unattended && num_disks >= 1)) { - selected_disks = hw_select_first_disk(disks); + selected_disks = hw_select_first_disk((const struct hw_disk**)disks); // more than one usable disk has been found and // the user needs to choose what to do with them @@ -531,7 +579,7 @@ int main(int argc, char *argv[]) { int disk_selection[num_disks]; for (unsigned int i = 0; i < num_disks; i++) { - disk_names[i] = &disks[i]->description; + disk_names[i] = disks[i]->description; disk_selection[i] = 0; } @@ -562,7 +610,7 @@ int main(int argc, char *argv[]) { if (config.unattended) break; - num_selected_disks = hw_count_disks(selected_disks); + num_selected_disks = hw_count_disks((const struct hw_disk**)selected_disks); if (num_selected_disks == 1) { snprintf(message, sizeof(message), @@ -601,7 +649,7 @@ int main(int argc, char *argv[]) { hw_free_disks(disks); - struct hw_destination* destination = hw_make_destination(part_type, selected_disks); + struct hw_destination* destination = hw_make_destination(part_type, selected_disks, config.disable_swap); if (!destination) { errorbox(_("Your harddisk is too small.")); @@ -617,19 +665,21 @@ int main(int argc, char *argv[]) { fprintf(flog, "Memory : %lluMB\n", BYTES2MB(hw_memory())); // Warn the user if there is not enough space to create a swap partition - if (!config.unattended && !*destination->part_swap) { - rc = newtWinChoice(title, _("OK"), _("Cancel"), - _("Your harddisk is very small, but you can continue without a swap partition.")); + if (!config.unattended) { + if (!config.disable_swap && !*destination->part_swap) { + rc = newtWinChoice(title, _("OK"), _("Cancel"), + _("Your harddisk is very small, but you can continue without a swap partition.")); - if (rc != 1) - goto EXIT; + if (rc != 1) + goto EXIT; + } } // Filesystem selection if (!config.unattended) { struct filesystems { int fstype; - const char* description; + char* description; } filesystems[] = { { HW_FS_EXT4, _("ext4 Filesystem") }, { HW_FS_EXT4_WO_JOURNAL, _("ext4 Filesystem without journal") }, @@ -789,20 +839,55 @@ int main(int argc, char *argv[]) { free(backup_file); } + // Download and execute the postinstall script + if (*config.postinstall) { + snprintf(commandstring, sizeof(commandstring), + "/usr/bin/execute-postinstall.sh %s %s", DESTINATION_MOUNT_PATH, config.postinstall); + + if (runcommandwithstatus(commandstring, title, _("Running post-install script..."), logfile)) { + errorbox(_("Post-install script failed.")); + goto EXIT; + } + } + // Umount the destination drive - hw_umount_filesystems(destination, DESTINATION_MOUNT_PATH); + statuswindow(60, 4, title, _("Umounting filesystems...")); - // Stop the RAID array if we are using RAID - if (destination->is_raid) - hw_stop_all_raid_arrays(logfile); + rc = hw_umount_filesystems(destination, DESTINATION_MOUNT_PATH); + if (rc) { + // Show an error message if filesystems could not be umounted properly + snprintf(message, sizeof(message), + _("Could not umount all filesystems successfully:\n\n %s"), strerror(errno)); + errorbox(message); + goto EXIT; + } // Umount source drive and eject hw_umount(SOURCE_MOUNT_PATH); - snprintf(commandstring, STRING_SIZE, "/usr/bin/eject %s", sourcedrive); - mysystem(logfile, commandstring); + // Free downloaded ISO image + if (strcmp(sourcedrive, SOURCE_TEMPFILE) == 0) { + rc = unlink(sourcedrive); + if (rc) + fprintf(flog, "Could not free downloaded ISO image: %s\n", sourcedrive); - if (!config.unattended) { + // or eject real images + } else { + snprintf(commandstring, STRING_SIZE, "/usr/bin/eject %s", sourcedrive); + mysystem(logfile, commandstring); + } + newtPopWindow(); + + // Stop the RAID array if we are using RAID + if (destination->is_raid) + hw_stop_all_raid_arrays(logfile); + + // Show a short message that the installation went well and + // wait a moment so that all disk caches get flushed. + if (config.unattended) { + splashWindow(title, _("Unattended installation has finished. The system will be shutting down in a moment..."), 5); + + } else { snprintf(message, sizeof(message), _( "%s was successfully installed!\n\n" "Please remove any installation mediums from this system and hit the reboot button. " @@ -825,19 +910,28 @@ EXIT: newtFinished(); // Free resources - free(system_release); - free(roottext); - free(helpline); + if (system_release) + free(system_release); + + if (roottext) + free(roottext); + + if (helpline) + free(helpline); + + if (sourcedrive) + free(sourcedrive); - free(sourcedrive); - free(destination); + if (destination) + free(destination); hw_stop_all_raid_arrays(logfile); if (selected_disks) hw_free_disks(selected_disks); - hw_free(hw); + if (hw) + hw_free(hw); fcloseall();