summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/ka.c
blob: 670abe5af1d33cc514265f2260a57ecfb7c74f4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 * 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 <sys/mount.h>
#include "mount.h"
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#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<press Enter>\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<press Enter>\n", ka_launch[0]);
	//  log_message("KA: Can't execute %s\n<press Enter>\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;
}