xref: /freebsd/contrib/dialog/samples/install/setup.c (revision a4e5e0106ac7145f56eb39a691e302cabb4635be)
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
35 error(const char *s)
36 {
37     fprintf(stderr, "%s: %s\n", progname, s);
38     exit(1);
39 }
40 
41 static int
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
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
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
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
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
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
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
227 install_premounted(void)
228 {
229     extract_packages("");
230 }
231 
232 static 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
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
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
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