/* * Copyright 2005 Mandriva * * This software may be freely redistributed under the terms of the GNU * public license. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "ka.h" #include #include "mount.h" #include #include #include #include #include #include #include #include "config-stage1.h" #include "frontend.h" #include "log.h" #include "tools.h" struct in_addr next_server = { 0 }; #if 0 static void save_stuff_for_rescue(void) { copy_file("/etc/resolv.conf", STAGE2_LOCATION "/etc/resolv.conf", NULL); } #endif static void my_pause(void) { unsigned char t; fflush(stdout); read(0, &t, 1); } static enum return_type ka_wait_for_stage2(int count) { char * ramdisk = "/dev/ram3"; /* warning, verify that this file exists in the initrd*/ char * ka_launch[] = { "/ka/ka-d-client", "-w","-s","getstage2","-e","(cd /tmp/stage2; tar -x -f - )", NULL }; /* The command line for ka_launch */ char * mkfs_launch[] = { "/sbin/mke2fs", "-m", "0", ramdisk, NULL}; /* The mkfs command for formating the ramdisk */ log_message("KA: Preparing to receive stage 2...."); wait_message("Preparing to receive stage 2"); int pida, wait_status; if (!(pida = fork())) { /* Forking current process for running mkfs */ //close(1); close(2); execv(mkfs_launch[0], mkfs_launch); /* Formating the ramdisk */ printf("KA: Can't execute %s\n\n", mkfs_launch[0]); my_pause(); return KAERR_CANTFORK; } while (wait4(-1, &wait_status, 0, NULL) != pida) {}; /* Waiting the end of mkfs */ remove_wait_message(); wait_message("Mounting /dev/ram3 at %s", STAGE2_LOCATION); if (my_mount(ramdisk, STAGE2_LOCATION, "ext2", 1)) {/* Trying to mount the ramdisk */ return RETURN_ERROR; } remove_wait_message(); log_message("KA: Waiting for stage 2...."); wait_message("Waiting for rescue from KA server (Try %d/%d)", count, KA_MAX_RETRY); pid_t pid; /* Process ID of the child process */ pid_t wpid; /* Process ID from wait() */ int status; /* Exit status from wait() */ pid = fork(); if ( pid == -1 ) { fprintf(stderr, "%s: Failed to fork()\n", strerror(errno)); exit(13); } else if ( pid == 0 ) { // close(2); execv(ka_launch[0], ka_launch); } else { // wpid = wait(&status); /* Child's exit status */ wpid = wait4(-1, &status, 0, NULL); if ( wpid == -1 ) { fprintf(stderr,"%s: wait()\n", strerror(errno)); return RETURN_ERROR; } else if ( wpid != pid ) abort(); else { if ( WIFEXITED(status) ) { printf("Exited: $? = %d\n", WEXITSTATUS(status)); } else if ( WIFSIGNALED(status) ) { printf("Signal: %d%s\n", WTERMSIG(status), WCOREDUMP(status) ? " with core file." : ""); } } } remove_wait_message(); return RETURN_OK; // if (!(pid = fork())) { /* Froking current process for running ka-deploy (client side) */ // close(1); /* Closing stdout */ // close(2); /* Closing stderr */ // execve(ka_launch[0], ka_launch,grab_env()); /* Running ka-deploy (client side) */ // printf("KA: Can't execute %s\n\n", ka_launch[0]); // log_message("KA: Can't execute %s\n\n", ka_launch[0]); // my_pause(); // return KAERR_CANTFORK; //} //while (wait4(-1, &wait_status, 0, NULL) != pid) {}; /* Waiting the end of duplication */ // log_message("kalaunch ret %d\n", WIFEXITED(wait_status)); // remove_wait_message(); //sleep(100000); // return RETURN_OK; } enum return_type perform_ka(void) { enum return_type results; int server_failure = 1; /* Number of time we've failed to find a ka server */ FILE *f = fopen ("/ka/tftpserver","w"); if (f != NULL) { /* Writing the NEXT_SERVER value of the DHCP Request in the /ka/tftpserver file */ fprintf(f,"%s\n",inet_ntoa(next_server)); fclose(f); } log_message("KA: Trying to retrieve stage2 from server"); log_message("KA: ka_wait_for_stage2"); do { /* We are trying to get a valid stage 2 (rescue) */ results=ka_wait_for_stage2(server_failure); if (results != RETURN_OK) { return results; } else { /* Trying to open STAGE2_LOCATION/ka directory */ char dir[255] = STAGE2_LOCATION; strcat(dir,"/ka"); DIR *dp = opendir(dir); /* Does the STAGE2_LOCATION/ka directory exists ? = Does the rescue with ka well downloaded ?*/ if (!dp) { log_message("KA: Server not found !"); /* Be sure that the STAGE2_LOCATION isn't mounted after receiving a wrong rescue */ if (umount (STAGE2_LOCATION)) { log_perror("KA: Unable to umount STAGE2"); } int cpt; if (server_failure++ == KA_MAX_RETRY){ /* if the KA server can't be reach KA_MAX_RETRY times */ char * reboot_launch[] = { "/sbin/reboot", NULL}; for (cpt=5; cpt>0; cpt--) { wait_message("!!! Can't reach a valid KA server !!! (Rebooting in %d sec)",cpt); sleep (1); } /* Rebooting the computer to avoid infinite loop on ka mode */ execv(reboot_launch[0], reboot_launch); } for (cpt=5; cpt>0; cpt--) { wait_message("KA server not found ! (Try %d/%d in %d sec)",server_failure,KA_MAX_RETRY,cpt); log_message("Ka not found %d/%d", server_failure,KA_MAX_RETRY); sleep (1); } remove_wait_message(); /* We should try another time*/ results=RETURN_BACK; continue; } if (dp) { log_message("KA: Stage 2 downloaded successfully"); closedir(dp); /* Closing the /ka directory */ server_failure=1; /* Resetting server_failure */ results = RETURN_OK; } } log_message("KA: Preparing chroot"); return RETURN_OK; // if (IS_RESCUE) { /* if we are in rescue mode */ // save_stuff_for_rescue(); /* Saving resolve.conf */ // if (umount (STAGE2_LOCATION)) { /* Unmounting STAGE2 elseif kernel can't mount it ! */ // log_perror("KA: Unable to umount STAGE2"); // return RETURN_ERROR; // } // } } while (results == RETURN_BACK); // method_name = strdup("ka"); return RETURN_OK; }