1 /* Copyright (C) 1995 Florian La Roche */
2 /* Who wants to help coding? I don't like doing this... */
3
4 /* You can just start setup as normal user and see how far it is coded
5 right now. This will do a fake installation and won't actually change
6 any data on your computer. */
7
8 /* TODO: write a good package selection code
9 change functions to return better error code
10 */
11
12 /* Show an extra text-box with the contents of all external commands,
13 before they are executed. So you can abort the installation, if any
14 wrong commands are to be executed. (So don't format wrong partition.) */
15 #define VERBOSE 1
16
17 /* If defined, don't actually execute any comands and don't actually modify
18 any files. So you can test any possible installation without doing any
19 damage to your computer.
20 The file FDISK.TEST is used instead of real "fdisk -l" output, so that
21 it can be started as normal user. */
22 #define DEBUG_THIS 1
23
24 #include <dialog.h>
25
26 /* max length of a partition name like e.g. '/dev/hda1' */
27 #define MAX_DEV_NAME 25
28
29 /* max number of possible Linux/Swap/MsDos partitions */
30 #define MAX_PARTS 20
31
32 char *progname = NULL;
33
34 static void
error(const char * s)35 error(const char *s)
36 {
37 fprintf(stderr, "%s: %s\n", progname, s);
38 exit(1);
39 }
40
41 static int
my_system(const char * s,...)42 my_system(const char *s,...)
43 {
44 int ret, i;
45 va_list ap;
46 char sh[200];
47
48 va_start(ap, s);
49 vsprintf(sh, s, ap);
50 va_end(ap);
51
52 #ifdef VERBOSE
53 i = dialog_msgbox("I will run the following command:", sh, 10, 65, 1);
54 dialog_clear();
55 #ifdef DEBUG_THIS
56 return 0;
57 #endif
58 #endif
59 ret = system(sh);
60 if (!(ret >> 8))
61 return 0;
62 i = dialog_msgbox("Error-Exit on the following command:",
63 sh, 12, 73, 1);
64 dialog_clear();
65 return 1;
66 }
67
68 /* We support to install from DOS/Linux-partitions. */
69 enum partition_type {
70 MsDos,
71 Linux,
72 Swap
73 };
74
75 struct partition {
76 enum partition_type type;
77 char name[MAX_DEV_NAME];
78 int blocks;
79 int flag;
80 } partitions[MAX_PARTS];
81 int num_partition = 0;
82 int num_linux = 0;
83 int num_swap = 0;
84 int num_msdos = 0;
85
86 static int
get_line(char * line,int size,FILE * f)87 get_line(char *line, int size, FILE * f)
88 {
89 char *ptr = line;
90 int c;
91
92 if (feof(f))
93 return -1;
94 while (size-- && ((c = getc(f)) != EOF) && (c != '\n'))
95 *ptr++ = c;
96 *ptr++ = '\0';
97 return (int) (ptr - line);
98 }
99
100 static void
read_partitions(void)101 read_partitions(void)
102 {
103 FILE *f;
104 char line[200];
105 int length;
106 #ifndef DEBUG_THIS
107 int ret = system("fdisk -l 2>/dev/null 1>/tmp/fdisk.output");
108 if ((ret >> 8) != 0) {
109 error("fdisk didn't run");
110 }
111 if ((f = fopen("/tmp/fdisk.output", "r")) == NULL)
112 #else
113 if ((f = fopen("FDISK.TEST", "r")) == NULL)
114 #endif
115 error("cannot read fdisk output");
116
117 while (num_partition <= MAX_PARTS
118 && (length = get_line(line, 200, f)) >= 0) {
119 if (strncmp(line, "/dev/", 5) == 0) {
120 int n = 0;
121 char *s = line + 5;
122 char *t = partitions[num_partition].name;
123 strcpy(t, "/dev/");
124 t += 5;
125 while (n < MAX_DEV_NAME && *s != '\0'
126 && !isspace((unsigned char) *s)) {
127 *t++ = *s++;
128 n++;
129 }
130 *t = '\0';
131 /* Read the size of the partition. */
132 t = line + 37;
133 while (isspace((unsigned char) *t))
134 t++;
135 partitions[num_partition].blocks = atoi(t);
136 if (strstr(line, "Linux native")) {
137 partitions[num_partition].type = Linux;
138 num_partition++;
139 num_linux++;
140 } else if (strstr(line, "Linux swap")) {
141 partitions[num_partition].type = Swap;
142 num_partition++;
143 num_swap++;
144 } else if (strstr(line, "DOS")) {
145 partitions[num_partition].type = MsDos;
146 num_partition++;
147 num_msdos++;
148 }
149 }
150 }
151 fclose(f);
152 #ifndef DEBUG_THIS
153 unlink("/tmp/fdisk.output");
154 #endif
155 }
156
157 static int
select_partition(const char * title,const char * prompt,int y,int x)158 select_partition(const char *title, const char *prompt, int y, int x)
159 {
160 int i, num, ret;
161 char info[MAX_PARTS][40];
162 char *items[MAX_PARTS * 2];
163 int num_pa[MAX_PARTS];
164
165 num = 0;
166 for (i = 0; i < num_partition; i++) {
167 if (partitions[i].type == Linux) {
168 items[num * 2] = partitions[i].name;
169 sprintf(info[num], "Linux partition with %d blocks",
170 partitions[i].blocks);
171 items[num * 2 + 1] = info[num];
172 num_pa[num] = i;
173 num++;
174 }
175 }
176 ret = dialog_menu(title, prompt, y + num, x, num, num, items);
177 dialog_clear();
178 if (ret >= 0) /* item selected */
179 ret = num_pa[ret];
180 return ret;
181 }
182
183 static int
select_install_partition(void)184 select_install_partition(void)
185 {
186 return select_partition("Select Install Partition",
187 "\\nWhere do you want to install Linux?\\n", 9, 60);
188 }
189
190 static int
select_source_partition(void)191 select_source_partition(void)
192 {
193 return select_partition("Select Source Partition",
194 "\\nOn which partition is the source?\\n", 9, 60);
195 }
196
197 const char *null = ">/dev/null 2>/dev/null";
198 const char *install_partition = NULL;
199
200 static void
extract_packages(const char * source_path)201 extract_packages(const char *source_path)
202 {
203 #ifndef DEBUG_THIS
204 FILE *f;
205 #endif
206
207 if (my_system("mkdir -p /install/var/installed/packages %s", null))
208 return;
209 if (my_system("cd /install; for i in /source%s/*.tgz; do "
210 "tar xzplvvkf $i >> var/installed/packages/base "
211 "2>>var/installed/packages/ERROR; done", source_path))
212 return;
213 #ifndef DEBUG_THIS
214 if ((f = fopen("/install/etc/fstab", "w")) == NULL) {
215 /* i = */ dialog_msgbox("Error", "Cannot write /etc/fstab",
216 12, 40, 1);
217 return;
218 }
219 fprintf(f, "%s / ext2 defaults 1 1\n", install_partition);
220 fprintf(f, "none /proc proc defaults 0 2\n");
221 /* XXX write swap-partitions */
222 fclose(f);
223 #endif
224 }
225
226 static void
install_premounted(void)227 install_premounted(void)
228 {
229 extract_packages("");
230 }
231
232 static void
install_harddisk(void)233 install_harddisk(void)
234 {
235 const char *name;
236 int part, ret;
237
238 if ((part = select_source_partition()) <= -1)
239 return;
240 name = partitions[part].name;
241
242 if (my_system("mount -t ext2 %s /source %s", name, null))
243 return;
244 ret = dialog_inputbox("Path in partition",
245 "Please enter the directory in which the "
246 "source files are.", 13, 50, "", FALSE);
247 dialog_clear();
248 if (ret != 0)
249 return;
250 /* XXX strdup */
251 extract_packages(strdup(dialog_input_result));
252 if (my_system("umount /source %s", null))
253 return;
254 }
255
256 static void
install_nfs(void)257 install_nfs(void)
258 {
259 if (my_system("ifconfig eth0 134.96.81.36 netmask 255.255.255.224 "
260 "broadcast 134.96.81.63 %s", null))
261 return;
262 if (my_system("route add -net 134.96.81.32 %s", null))
263 return;
264 if (my_system("mount -t nfs 134.96.81.38:"
265 "/local/ftp/pub/linux/ELF.binary/tar /source %s", null))
266 return;
267 extract_packages("/base");
268 if (my_system("umount /source %s", null))
269 return;
270 if (my_system("ifconfig eth0 down %s", null))
271 return;
272 }
273
274 static void
main_install(void)275 main_install(void)
276 {
277 int part, ret;
278 const char *name;
279 char *items1[] =
280 {
281 "1", "Harddisk Install",
282 "2", "Network Install(NFS)",
283 "3", "Premounted on /source"
284 };
285
286 if (num_linux == 0) {
287 /* XXX */
288 return;
289 }
290 if ((part = select_install_partition()) <= -1)
291 return;
292 install_partition = name = partitions[part].name;
293 if (my_system("mke2fs %s %s", name, null))
294 return;
295 if (my_system("mount -t ext2 %s /install %s", name, null))
296 return;
297 ret = dialog_menu("Choose install medium",
298 "\\nPlease say from where you want to install.\\n",
299 12, 62, 3, 3, items1);
300 dialog_clear();
301 switch (ret) {
302 case 0:
303 install_harddisk();
304 break;
305 case 1:
306 install_nfs();
307 break;
308 case 2:
309 install_premounted();
310 break;
311 case -2: /* cancel */
312 case -1:
313 break; /* esc */
314 }
315 if (my_system("umount /install %s", null))
316 return;
317 }
318
319 int
main(int argc,char ** argv)320 main(int argc, char **argv)
321 {
322 int stop = 0;
323 int ret;
324 char *items1[] =
325 {
326 "1", "Display a help text",
327 "2", "Start an installation",
328 "3", "Exit to the shell"
329 };
330
331 progname = argv[0];
332
333 read_partitions();
334 if (num_linux == 0) {
335 printf("\n\nPlease start \"fdisk\" or \"cfdisk\" and create a"
336 "\nnative Linux-partition to install Linux on.\n\n");
337 exit(1);
338 }
339
340 init_dialog();
341
342 while (!stop) {
343 ret = dialog_menu("Linux Install Utility",
344 "\\nCopyright (C) 1995 Florian La Roche\\n"
345 "\\nPre-Alpha version, be careful, read the doc!!!"
346 "\\nemail: florian@jurix.jura.uni-sb.de, "
347 "flla@stud.uni-sb.de\\n",
348 15, 64, 3, 3, items1);
349 dialog_clear();
350 switch (ret) {
351 case 0:
352 ret = dialog_textbox("Help Text",
353 "setup.help", 20, 70);
354 dialog_clear();
355 break;
356 case 1:
357 main_install();
358 break;
359 case 2:
360 stop = 1;
361 break;
362 case -2: /* cancel */
363 case -1:
364 stop = 1; /* esc */
365 }
366 }
367 end_dialog();
368 printf("\nExecute \"reboot\" to restart your computer...\n");
369
370 exit(0);
371 }
372