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