1 /* 2 * Mach Operating System 3 * Copyright (c) 1992 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the 9 * software, derivative works or modified versions, and any portions 10 * thereof, and that both notices appear in supporting documentation. 11 * 12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15 * 16 * Carnegie Mellon requests users of this software to return to 17 * 18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19 * School of Computer Science 20 * Carnegie Mellon University 21 * Pittsburgh PA 15213-3890 22 * 23 * any improvements or extensions that they make and grant Carnegie Mellon 24 * the rights to redistribute these changes. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/disklabel.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <errno.h> 32 #include <sys/stat.h> 33 #include <sys/ioctl.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 37 int iotest; 38 39 #define LBUF 100 40 static char lbuf[LBUF]; 41 42 /* 43 * 44 * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 45 * 46 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 47 * Copyright (c) 1989 Robert. V. Baron 48 * Created. 49 */ 50 51 #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 52 #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 53 #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 54 55 #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 56 57 #define SECSIZE 512 58 59 const char *disk; 60 const char *disks[] = 61 { 62 "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 63 }; 64 65 char *name; 66 67 struct disklabel disklabel; /* disk parameters */ 68 69 int cyls, sectors, heads, cylsecs, disksecs; 70 71 struct mboot 72 { 73 unsigned char padding[2]; /* force the longs to be long alligned */ 74 unsigned char bootinst[DOSPARTOFF]; 75 struct dos_partition parts[4]; 76 unsigned short int signature; 77 }; 78 struct mboot mboot; 79 80 #define ACTIVE 0x80 81 #define BOOT_MAGIC 0xAA55 82 83 int dos_cyls; 84 int dos_heads; 85 int dos_sectors; 86 int dos_cylsecs; 87 88 #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 89 #define DOSCYL(c) (c & 0xff) 90 static int partition = -1; 91 92 93 static int a_flag = 0; /* set active partition */ 94 static int i_flag = 0; /* replace partition data */ 95 static int u_flag = 0; /* update partition data */ 96 97 static unsigned char bootcode[] = { 98 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 99 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 100 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 101 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 102 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 103 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 104 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 105 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 106 0xeb, 0xf4, 0xfb, 0xeb, 0xfe, 107 'M', 'i', 's', 's', 'i', 'n', 'g', ' ', 108 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 109 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ', 110 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 111 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ', 112 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0, 113 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ', 114 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0, 115 116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 129 }; 130 131 struct part_type 132 { 133 unsigned char type; 134 char *name; 135 }part_types[] = 136 { 137 {0x00, "unused"} 138 ,{0x01, "Primary DOS with 12 bit FAT"} 139 ,{0x02, "XENIX / filesystem"} 140 ,{0x03, "XENIX /usr filesystem"} 141 ,{0x04, "Primary DOS with 16 bit FAT"} 142 ,{0x05, "Extended DOS"} 143 ,{0x06, "Primary 'big' DOS (> 32MB)"} 144 ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"} 145 ,{0x08, "AIX filesystem"} 146 ,{0x09, "AIX boot partition or Coherent"} 147 ,{0x0A, "OS/2 Boot Manager or OPUS"} 148 ,{0x10, "OPUS"} 149 ,{0x40, "VENIX 286"} 150 ,{0x50, "DM"} 151 ,{0x51, "DM"} 152 ,{0x52, "CP/M or Microport SysV/AT"} 153 ,{0x56, "GB"} 154 ,{0x61, "Speed"} 155 ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 156 ,{0x64, "Novell Netware 2.xx"} 157 ,{0x65, "Novell Netware 3.xx"} 158 ,{0x75, "PCIX"} 159 ,{0x80, "Minix 1.1 ... 1.4a"} 160 ,{0x81, "Minix 1.4b ... 1.5.10"} 161 ,{0x82, "Linux swap"} 162 ,{0x83, "Linux filesystem"} 163 ,{0x93, "Amoeba filesystem"} 164 ,{0x94, "Amoeba bad block table"} 165 ,{0xA5, "FreeBSD/NetBSD/386BSD"} 166 ,{0xA7, "NEXTSTEP"} 167 ,{0xB7, "BSDI BSD/386 filesystem"} 168 ,{0xB8, "BSDI BSD/386 swap"} 169 ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 170 ,{0xE1, "Speed"} 171 ,{0xE3, "Speed"} 172 ,{0xE4, "Speed"} 173 ,{0xF1, "Speed"} 174 ,{0xF2, "DOS 3.3+ Secondary"} 175 ,{0xF4, "Speed"} 176 ,{0xFF, "BBT (Bad Blocks Table)"} 177 }; 178 179 static void print_s0(int which); 180 static void print_part(int i); 181 static void init_sector0(unsigned long start); 182 static void change_part(int i); 183 static void print_params(); 184 static void change_active(int which); 185 static void get_params_to_use(); 186 static void dos(int sec, unsigned char *c, unsigned char *s, unsigned char *h); 187 static int open_disk(int u_flag); 188 static ssize_t read_disk(off_t sector, void *buf); 189 static ssize_t write_disk(off_t sector, void *buf); 190 static int get_params(); 191 static int read_s0(); 192 static int write_s0(); 193 static int ok(char *str); 194 static int decimal(char *str, int *num, int deflt); 195 static char *get_type(int type); 196 #if 0 197 static int hex(char *str, int *num, int deflt); 198 static int string(char *str, char **ans); 199 #endif 200 201 202 int 203 main(int argc, char *argv[]) 204 { 205 int i; 206 207 name = *argv; 208 {register char *cp = name; 209 while (*cp) if (*cp++ == '/') name = cp; 210 } 211 212 for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 213 if (*token++ != '-' || !*token) 214 break; 215 else { register int flag; 216 for ( ; (flag = *token++) ; ) { 217 switch (flag) { 218 case '0': 219 partition = 0; 220 break; 221 case '1': 222 partition = 1; 223 break; 224 case '2': 225 partition = 2; 226 break; 227 case '3': 228 partition = 3; 229 break; 230 case 'a': 231 a_flag = 1; 232 break; 233 case 'i': 234 i_flag = 1; 235 case 'u': 236 u_flag = 1; 237 break; 238 default: 239 goto usage; 240 } 241 } 242 } 243 } 244 245 if (argc > 0) 246 { 247 static char realname[12]; 248 249 if(strncmp(argv[0], "/dev", 4) == 0) 250 disk = argv[0]; 251 else 252 { 253 snprintf(realname, 12, "/dev/r%s", argv[0]); 254 disk = realname; 255 } 256 257 if (open_disk(u_flag) < 0) 258 { 259 fprintf(stderr, "Cannot open disk %s (%s)\n", 260 disk, sys_errlist[errno]); 261 exit(1); 262 } 263 } 264 else 265 { 266 int i, rv = 0; 267 268 for(i = 0; disks[i]; i++) 269 { 270 disk = disks[i]; 271 rv = open_disk(u_flag); 272 if(rv != -2) break; 273 } 274 if(rv < 0) 275 { 276 fprintf(stderr, "Cannot open any disk (%s)\n", 277 sys_errlist[errno]); 278 exit(1); 279 } 280 } 281 282 printf("******* Working on device %s *******\n",disk); 283 if(u_flag) 284 { 285 get_params_to_use(); 286 } 287 else 288 { 289 print_params(); 290 } 291 292 if (read_s0()) 293 init_sector0(1); 294 295 printf("Warning: BIOS sector numbering starts with sector 1\n"); 296 printf("Information from DOS bootblock is:\n"); 297 if (partition == -1) 298 for (i = 0; i < NDOSPART; i++) 299 change_part(i); 300 else 301 change_part(partition); 302 303 if (u_flag || a_flag) 304 change_active(partition); 305 306 if (u_flag || a_flag) { 307 printf("\nWe haven't changed the partition table yet. "); 308 printf("This is your last chance.\n"); 309 print_s0(-1); 310 if (ok("Should we write new partition table?")) 311 write_s0(); 312 } 313 314 exit(0); 315 316 usage: 317 printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n"); 318 return(1); 319 } 320 321 static void 322 print_s0(int which) 323 { 324 int i; 325 326 print_params(); 327 printf("Information from DOS bootblock is:\n"); 328 if (which == -1) 329 for (i = 0; i < NDOSPART; i++) 330 printf("%d: ", i), print_part(i); 331 else 332 print_part(which); 333 } 334 335 static struct dos_partition mtpart = { 0 }; 336 337 static void 338 print_part(int i) 339 { 340 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 341 342 343 if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 344 printf("<UNUSED>\n"); 345 return; 346 } 347 printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 348 printf(" start %ld, size %ld (%ld Meg), flag %x\n", 349 partp->dp_start, 350 partp->dp_size, partp->dp_size * 512 / (1024 * 1024), 351 partp->dp_flag); 352 printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 353 ,DPCYL(partp->dp_scyl, partp->dp_ssect) 354 ,DPSECT(partp->dp_ssect) 355 ,partp->dp_shd 356 ,DPCYL(partp->dp_ecyl, partp->dp_esect) 357 ,DPSECT(partp->dp_esect) 358 ,partp->dp_ehd); 359 } 360 361 static void 362 init_sector0(unsigned long start) 363 { 364 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 365 unsigned long size = disksecs - start; 366 367 memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 368 mboot.signature = BOOT_MAGIC; 369 370 partp->dp_typ = DOSPTYP_386BSD; 371 partp->dp_flag = ACTIVE; 372 partp->dp_start = start; 373 partp->dp_size = size; 374 375 dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 376 dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 377 } 378 379 static void 380 change_part(int i) 381 { 382 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 383 384 printf("The data for partition %d is:\n", i); 385 print_part(i); 386 387 if (u_flag && ok("Do you want to change it?")) { 388 int tmp; 389 390 if (i_flag) { 391 bzero((char *)partp, sizeof (struct dos_partition)); 392 if (i == 3) { 393 init_sector0(1); 394 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); 395 print_part(i); 396 } 397 } 398 399 do { 400 Decimal("sysid", partp->dp_typ, tmp); 401 Decimal("start", partp->dp_start, tmp); 402 Decimal("size", partp->dp_size, tmp); 403 404 if (ok("Explicitly specifiy beg/end address ?")) 405 { 406 int tsec,tcyl,thd; 407 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 408 thd = partp->dp_shd; 409 tsec = DPSECT(partp->dp_ssect); 410 Decimal("beginning cylinder", tcyl, tmp); 411 Decimal("beginning head", thd, tmp); 412 Decimal("beginning sector", tsec, tmp); 413 partp->dp_scyl = DOSCYL(tcyl); 414 partp->dp_ssect = DOSSECT(tsec,tcyl); 415 partp->dp_shd = thd; 416 417 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 418 thd = partp->dp_ehd; 419 tsec = DPSECT(partp->dp_esect); 420 Decimal("ending cylinder", tcyl, tmp); 421 Decimal("ending head", thd, tmp); 422 Decimal("ending sector", tsec, tmp); 423 partp->dp_ecyl = DOSCYL(tcyl); 424 partp->dp_esect = DOSSECT(tsec,tcyl); 425 partp->dp_ehd = thd; 426 } else { 427 dos(partp->dp_start, 428 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 429 dos(partp->dp_start+partp->dp_size - 1, 430 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 431 } 432 433 print_part(i); 434 } while (!ok("Are we happy with this entry?")); 435 } 436 } 437 438 static void 439 print_params() 440 { 441 printf("parameters extracted from in-core disklabel are:\n"); 442 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 443 ,cyls,heads,sectors,cylsecs); 444 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 445 printf(" Figures below won't work with BIOS for partitions not in cyl 1\n"); 446 printf("parameters to be used for BIOS calculations are:\n"); 447 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 448 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 449 } 450 451 static void 452 change_active(int which) 453 { 454 int i; 455 int active = 3, tmp; 456 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 457 458 if (a_flag && which != -1) 459 active = which; 460 if (!ok("Do you want to change the active partition?")) 461 return; 462 do 463 Decimal("active partition", active, tmp); 464 while (!ok("Are you happy with this choice")); 465 for (i = 0; i < NDOSPART; i++) 466 partp[i].dp_flag = 0; 467 if (active >= 0 && active < NDOSPART) 468 partp[active].dp_flag = ACTIVE; 469 } 470 471 void 472 get_params_to_use() 473 { 474 int tmp; 475 print_params(); 476 if (ok("Do you want to change our idea of what BIOS thinks ?")) 477 { 478 do 479 { 480 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 481 Decimal("BIOS's idea of #heads", dos_heads, tmp); 482 Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 483 dos_cylsecs = dos_heads * dos_sectors; 484 print_params(); 485 } 486 while(!ok("Are you happy with this choice")); 487 } 488 } 489 490 /***********************************************\ 491 * Change real numbers into strange dos numbers * 492 \***********************************************/ 493 static void 494 dos(sec, c, s, h) 495 int sec; 496 unsigned char *c, *s, *h; 497 { 498 int cy; 499 int hd; 500 501 if (sec == 0) { 502 *s = *c = *h = 0; 503 return; 504 } 505 506 cy = sec / ( dos_cylsecs ); 507 sec = sec - cy * ( dos_cylsecs ); 508 509 hd = sec / dos_sectors; 510 sec = (sec - hd * dos_sectors) + 1; 511 512 *h = hd; 513 *c = cy & 0xff; 514 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 515 } 516 517 int fd; 518 519 /* Getting device status */ 520 521 static int 522 open_disk(int u_flag) 523 { 524 struct stat st; 525 526 if (stat(disk, &st) == -1) { 527 fprintf(stderr, "%s: Can't get file status of %s\n", 528 name, disk); 529 return -1; 530 } 531 if ( !(st.st_mode & S_IFCHR) ) 532 fprintf(stderr,"%s: Device %s is not character special\n", 533 name, disk); 534 if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 535 if(errno == ENXIO) 536 return -2; 537 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 538 return -1; 539 } 540 if (get_params(0) == -1) { 541 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 542 name, disk); 543 return -1; 544 } 545 return fd; 546 } 547 548 static ssize_t 549 read_disk(off_t sector, void *buf) 550 { 551 lseek(fd,(sector * 512), 0); 552 return read(fd, buf, 512); 553 } 554 555 static ssize_t 556 write_disk(off_t sector, void *buf) 557 { 558 lseek(fd,(sector * 512), 0); 559 return write(fd, buf, 512); 560 } 561 562 static int 563 get_params() 564 { 565 566 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 567 fprintf(stderr, 568 "%s: Can't get disk parameters on %s; supplying dummy ones\n", 569 name, disk); 570 dos_cyls = cyls = 1; 571 dos_heads = heads = 1; 572 dos_sectors = sectors = 1; 573 dos_cylsecs = cylsecs = heads * sectors; 574 disksecs = cyls * heads * sectors; 575 return disksecs; 576 } 577 578 dos_cyls = cyls = disklabel.d_ncylinders; 579 dos_heads = heads = disklabel.d_ntracks; 580 dos_sectors = sectors = disklabel.d_nsectors; 581 dos_cylsecs = cylsecs = heads * sectors; 582 disksecs = cyls * heads * sectors; 583 584 return (disksecs); 585 } 586 587 588 static int 589 read_s0() 590 { 591 if (read_disk(0, (char *) mboot.bootinst) == -1) { 592 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 593 return -1; 594 } 595 if (mboot.signature != BOOT_MAGIC) { 596 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 597 name); 598 /* So should we initialize things */ 599 return -1; 600 } 601 return 0; 602 } 603 604 static int 605 write_s0() 606 { 607 int flag; 608 if (iotest) { 609 print_s0(-1); 610 return 0; 611 } 612 /* 613 * write enable label sector before write (if necessary), 614 * disable after writing. 615 * needed if the disklabel protected area also protects 616 * sector 0. (e.g. empty disk) 617 */ 618 flag = 1; 619 #ifdef NOT_NOW 620 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 621 perror("ioctl DIOCWLABEL"); 622 #endif 623 if (write_disk(0, (char *) mboot.bootinst) == -1) { 624 fprintf(stderr, "%s: Can't write fdisk partition table\n", 625 name); 626 return -1; 627 flag = 0; 628 #ifdef NOT_NOW 629 (void) ioctl(fd, DIOCWLABEL, &flag); 630 #endif 631 } 632 return(0); 633 } 634 635 636 static int 637 ok(str) 638 char *str; 639 { 640 printf("%s [n] ", str); 641 fgets(lbuf, LBUF, stdin); 642 lbuf[strlen(lbuf)-1] = 0; 643 644 if (*lbuf && 645 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 646 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 647 return 1; 648 else 649 return 0; 650 } 651 652 static int 653 decimal(char *str, int *num, int deflt) 654 { 655 int acc = 0, c; 656 char *cp; 657 658 while (1) { 659 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 660 fgets(lbuf, LBUF, stdin); 661 lbuf[strlen(lbuf)-1] = 0; 662 663 if (!*lbuf) 664 return 0; 665 666 cp = lbuf; 667 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 668 if (!c) 669 return 0; 670 while ((c = *cp++)) { 671 if (c <= '9' && c >= '0') 672 acc = acc * 10 + c - '0'; 673 else 674 break; 675 } 676 if (c == ' ' || c == '\t') 677 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 678 if (!c) { 679 *num = acc; 680 return 1; 681 } else 682 printf("%s is an invalid decimal number. Try again\n", 683 lbuf); 684 } 685 686 } 687 688 #if 0 689 static int 690 hex(char *str, int *num, int deflt) 691 { 692 int acc = 0, c; 693 char *cp; 694 695 while (1) { 696 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 697 fgets(lbuf, LBUF, stdin); 698 lbuf[strlen(lbuf)-1] = 0; 699 700 if (!*lbuf) 701 return 0; 702 703 cp = lbuf; 704 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 705 if (!c) 706 return 0; 707 while ((c = *cp++)) { 708 if (c <= '9' && c >= '0') 709 acc = (acc << 4) + c - '0'; 710 else if (c <= 'f' && c >= 'a') 711 acc = (acc << 4) + c - 'a' + 10; 712 else if (c <= 'F' && c >= 'A') 713 acc = (acc << 4) + c - 'A' + 10; 714 else 715 break; 716 } 717 if (c == ' ' || c == '\t') 718 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 719 if (!c) { 720 *num = acc; 721 return 1; 722 } else 723 printf("%s is an invalid hex number. Try again\n", 724 lbuf); 725 } 726 727 } 728 729 static int 730 string(char *str, char **ans) 731 { 732 int c; 733 char *cp = lbuf; 734 735 while (1) { 736 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 737 fgets(lbuf, LBUF, stdin); 738 lbuf[strlen(lbuf)-1] = 0; 739 740 if (!*lbuf) 741 return 0; 742 743 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 744 if (c == '"') { 745 c = *++cp; 746 *ans = cp; 747 while ((c = *cp) && c != '"') cp++; 748 } else { 749 *ans = cp; 750 while ((c = *cp) && c != ' ' && c != '\t') cp++; 751 } 752 753 if (c) 754 *cp = 0; 755 return 1; 756 } 757 } 758 #endif 759 760 static char * 761 get_type(int type) 762 { 763 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 764 int counter = 0; 765 struct part_type *ptr = part_types; 766 767 768 while(counter < numentries) 769 { 770 if(ptr->type == type) 771 { 772 return(ptr->name); 773 } 774 ptr++; 775 counter++; 776 } 777 return("unknown"); 778 } 779