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 <errno.h> 31 #include <sys/stat.h> 32 #include <sys/ioctl.h> 33 #include <fcntl.h> 34 35 int iotest; 36 37 #define LBUF 100 38 static char lbuf[LBUF]; 39 40 /* 41 * 42 * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 43 * 44 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 45 * Copyright (c) 1989 Robert. V. Baron 46 * Created. 47 */ 48 49 #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 50 #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 51 #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 52 53 #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 54 55 #define SECSIZE 512 56 57 const char *disk; 58 const char *disks[] = 59 { 60 "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 61 }; 62 63 char *name; 64 65 struct disklabel disklabel; /* disk parameters */ 66 67 int cyls, sectors, heads, cylsecs, disksecs; 68 69 struct mboot 70 { 71 unsigned char padding[2]; /* force the longs to be long alligned */ 72 unsigned char bootinst[DOSPARTOFF]; 73 struct dos_partition parts[4]; 74 unsigned short int signature; 75 }; 76 struct mboot mboot; 77 78 #define ACTIVE 0x80 79 #define BOOT_MAGIC 0xAA55 80 81 int dos_cyls; 82 int dos_heads; 83 int dos_sectors; 84 int dos_cylsecs; 85 86 #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 87 #define DOSCYL(c) (c & 0xff) 88 static int dos(); 89 char *get_type(); 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 180 main(argc, argv) 181 char **argv; 182 { 183 int i; 184 185 name = *argv; 186 {register char *cp = name; 187 while (*cp) if (*cp++ == '/') name = cp; 188 } 189 190 for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 191 if (*token++ != '-' || !*token) 192 break; 193 else { register int flag; 194 for ( ; flag = *token++ ; ) { 195 switch (flag) { 196 case '0': 197 partition = 0; 198 break; 199 case '1': 200 partition = 1; 201 break; 202 case '2': 203 partition = 2; 204 break; 205 case '3': 206 partition = 3; 207 break; 208 case 'a': 209 a_flag = 1; 210 break; 211 case 'i': 212 i_flag = 1; 213 case 'u': 214 u_flag = 1; 215 break; 216 default: 217 goto usage; 218 } 219 } 220 } 221 } 222 223 if (argc > 0) 224 { 225 static char realname[12]; 226 227 if(strncmp(argv[0], "/dev", 4) == 0) 228 disk = argv[0]; 229 else 230 { 231 snprintf(realname, 12, "/dev/r%s", argv[0]); 232 disk = realname; 233 } 234 235 if (open_disk(u_flag) < 0) 236 { 237 fprintf(stderr, "Cannot open disk %s (%s)\n", 238 disk, sys_errlist[errno]); 239 exit(1); 240 } 241 } 242 else 243 { 244 int i, rv; 245 246 for(i = 0; disks[i]; i++) 247 { 248 disk = disks[i]; 249 rv = open_disk(u_flag); 250 if(rv != -2) break; 251 } 252 if(rv < 0) 253 { 254 fprintf(stderr, "Cannot open any disk (%s)\n", 255 sys_errlist[errno]); 256 exit(1); 257 } 258 } 259 260 printf("******* Working on device %s *******\n",disk); 261 if(u_flag) 262 { 263 get_params_to_use(); 264 } 265 else 266 { 267 print_params(); 268 } 269 270 if (read_s0()) 271 init_sector0(1); 272 273 printf("Warning: BIOS sector numbering starts with sector 1\n"); 274 printf("Information from DOS bootblock is:\n"); 275 if (partition == -1) 276 for (i = 0; i < NDOSPART; i++) 277 change_part(i); 278 else 279 change_part(partition); 280 281 if (u_flag || a_flag) 282 change_active(partition); 283 284 if (u_flag || a_flag) { 285 printf("\nWe haven't changed the partition table yet. "); 286 printf("This is your last chance.\n"); 287 print_s0(-1); 288 if (ok("Should we write new partition table?")) 289 write_s0(); 290 } 291 292 exit(0); 293 294 usage: 295 printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n"); 296 } 297 298 print_s0(which) 299 { 300 int i; 301 302 print_params(); 303 printf("Information from DOS bootblock is:\n"); 304 if (which == -1) 305 for (i = 0; i < NDOSPART; i++) 306 printf("%d: ", i), print_part(i); 307 else 308 print_part(which); 309 } 310 311 static struct dos_partition mtpart = { 0 }; 312 313 print_part(i) 314 { 315 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 316 317 318 if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 319 printf("<UNUSED>\n"); 320 return; 321 } 322 printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 323 printf(" start %d, size %d (%d Meg), flag %x\n", 324 partp->dp_start, 325 partp->dp_size, partp->dp_size * 512 / (1024 * 1024), 326 partp->dp_flag); 327 printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 328 ,DPCYL(partp->dp_scyl, partp->dp_ssect) 329 ,DPSECT(partp->dp_ssect) 330 ,partp->dp_shd 331 ,DPCYL(partp->dp_ecyl, partp->dp_esect) 332 ,DPSECT(partp->dp_esect) 333 ,partp->dp_ehd); 334 } 335 336 init_sector0(start) 337 { 338 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 339 int size = disksecs - start; 340 int rest; 341 342 memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 343 mboot.signature = BOOT_MAGIC; 344 345 partp->dp_typ = DOSPTYP_386BSD; 346 partp->dp_flag = ACTIVE; 347 partp->dp_start = start; 348 partp->dp_size = size; 349 350 dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 351 dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 352 } 353 354 change_part(i) 355 { 356 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 357 358 printf("The data for partition %d is:\n", i); 359 print_part(i); 360 361 if (u_flag && ok("Do you want to change it?")) { 362 int tmp; 363 364 if (i_flag) { 365 bzero((char *)partp, sizeof (struct dos_partition)); 366 if (i == 3) { 367 init_sector0(1); 368 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); 369 print_part(i); 370 } 371 } 372 373 do { 374 Decimal("sysid", partp->dp_typ, tmp); 375 Decimal("start", partp->dp_start, tmp); 376 Decimal("size", partp->dp_size, tmp); 377 378 if (ok("Explicitly specifiy beg/end address ?")) 379 { 380 int tsec,tcyl,thd; 381 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 382 thd = partp->dp_shd; 383 tsec = DPSECT(partp->dp_ssect); 384 Decimal("beginning cylinder", tcyl, tmp); 385 Decimal("beginning head", thd, tmp); 386 Decimal("beginning sector", tsec, tmp); 387 partp->dp_scyl = DOSCYL(tcyl); 388 partp->dp_ssect = DOSSECT(tsec,tcyl); 389 partp->dp_shd = thd; 390 391 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 392 thd = partp->dp_ehd; 393 tsec = DPSECT(partp->dp_esect); 394 Decimal("ending cylinder", tcyl, tmp); 395 Decimal("ending head", thd, tmp); 396 Decimal("ending sector", tsec, tmp); 397 partp->dp_ecyl = DOSCYL(tcyl); 398 partp->dp_esect = DOSSECT(tsec,tcyl); 399 partp->dp_ehd = thd; 400 } else { 401 dos(partp->dp_start, 402 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 403 dos(partp->dp_start+partp->dp_size - 1, 404 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 405 } 406 407 print_part(i); 408 } while (!ok("Are we happy with this entry?")); 409 } 410 } 411 412 print_params() 413 { 414 printf("parameters extracted from in-core disklabel are:\n"); 415 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 416 ,cyls,heads,sectors,cylsecs); 417 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 418 printf(" Figures below won't work with BIOS for partitions not in cyl 1\n"); 419 printf("parameters to be used for BIOS calculations are:\n"); 420 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 421 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 422 } 423 424 change_active(which) 425 { 426 int i; 427 int active = 3, tmp; 428 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 429 430 if (a_flag && which != -1) 431 active = which; 432 if (!ok("Do you want to change the active partition?")) 433 return; 434 do 435 Decimal("active partition", active, tmp); 436 while (!ok("Are you happy with this choice")); 437 for (i = 0; i < NDOSPART; i++) 438 partp[i].dp_flag = 0; 439 if (active >= 0 && active < NDOSPART) 440 partp[active].dp_flag = ACTIVE; 441 } 442 443 get_params_to_use() 444 { 445 int tmp; 446 print_params(); 447 if (ok("Do you want to change our idea of what BIOS thinks ?")) 448 { 449 do 450 { 451 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 452 Decimal("BIOS's idea of #heads", dos_heads, tmp); 453 Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 454 dos_cylsecs = dos_heads * dos_sectors; 455 print_params(); 456 } 457 while(!ok("Are you happy with this choice")); 458 } 459 } 460 461 /***********************************************\ 462 * Change real numbers into strange dos numbers * 463 \***********************************************/ 464 static 465 dos(sec, c, s, h) 466 int sec; 467 unsigned char *c, *s, *h; 468 { 469 int cy; 470 int hd; 471 472 if (sec == 0) { 473 *s = *c = *h = 0; 474 return; 475 } 476 477 cy = sec / ( dos_cylsecs ); 478 sec = sec - cy * ( dos_cylsecs ); 479 480 hd = sec / dos_sectors; 481 sec = (sec - hd * dos_sectors) + 1; 482 483 *h = hd; 484 *c = cy & 0xff; 485 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 486 } 487 488 int fd; 489 490 /* Getting device status */ 491 492 open_disk(u_flag) 493 { 494 struct stat st; 495 496 if (stat(disk, &st) == -1) { 497 fprintf(stderr, "%s: Can't get file status of %s\n", 498 name, disk); 499 return -1; 500 } 501 if ( !(st.st_mode & S_IFCHR) ) 502 fprintf(stderr,"%s: Device %s is not character special\n", 503 name, disk); 504 if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 505 if(errno == ENXIO) 506 return -2; 507 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 508 return -1; 509 } 510 if (get_params(0) == -1) { 511 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 512 name, disk); 513 return -1; 514 } 515 return fd; 516 } 517 518 519 read_disk(sector, buf) 520 { 521 lseek(fd,(sector * 512), 0); 522 return read(fd, buf, 512); 523 } 524 525 write_disk(sector, buf) 526 { 527 lseek(fd,(sector * 512), 0); 528 return write(fd, buf, 512); 529 } 530 531 get_params(verbose) 532 { 533 534 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 535 fprintf(stderr, 536 "%s: Can't get disk parameters on %s; supplying dummy ones\n", 537 name, disk); 538 dos_cyls = cyls = 1; 539 dos_heads = heads = 1; 540 dos_sectors = sectors = 1; 541 dos_cylsecs = cylsecs = heads * sectors; 542 disksecs = cyls * heads * sectors; 543 return disksecs; 544 } 545 546 dos_cyls = cyls = disklabel.d_ncylinders; 547 dos_heads = heads = disklabel.d_ntracks; 548 dos_sectors = sectors = disklabel.d_nsectors; 549 dos_cylsecs = cylsecs = heads * sectors; 550 disksecs = cyls * heads * sectors; 551 552 return (disksecs); 553 } 554 555 556 read_s0() 557 { 558 if (read_disk(0, (char *) mboot.bootinst) == -1) { 559 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 560 return -1; 561 } 562 if (mboot.signature != BOOT_MAGIC) { 563 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 564 name); 565 /* So should we initialize things */ 566 return -1; 567 } 568 return 0; 569 } 570 571 write_s0() 572 { 573 int flag; 574 if (iotest) { 575 print_s0(-1); 576 return 0; 577 } 578 /* 579 * write enable label sector before write (if necessary), 580 * disable after writing. 581 * needed if the disklabel protected area also protects 582 * sector 0. (e.g. empty disk) 583 */ 584 flag = 1; 585 #ifdef NOT_NOW 586 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 587 perror("ioctl DIOCWLABEL"); 588 #endif 589 if (write_disk(0, (char *) mboot.bootinst) == -1) { 590 fprintf(stderr, "%s: Can't write fdisk partition table\n", 591 name); 592 return -1; 593 flag = 0; 594 #ifdef NOT_NOW 595 (void) ioctl(fd, DIOCWLABEL, &flag); 596 #endif 597 } 598 } 599 600 601 602 ok(str) 603 char *str; 604 { 605 printf("%s [n] ", str); 606 fgets(lbuf, LBUF, stdin); 607 lbuf[strlen(lbuf)-1] = 0; 608 609 if (*lbuf && 610 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 611 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 612 return 1; 613 else 614 return 0; 615 } 616 617 decimal(str, num, deflt) 618 char *str; 619 int *num; 620 { 621 int acc = 0, c; 622 char *cp; 623 624 while (1) { 625 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 626 fgets(lbuf, LBUF, stdin); 627 lbuf[strlen(lbuf)-1] = 0; 628 629 if (!*lbuf) 630 return 0; 631 632 cp = lbuf; 633 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 634 if (!c) 635 return 0; 636 while (c = *cp++) { 637 if (c <= '9' && c >= '0') 638 acc = acc * 10 + c - '0'; 639 else 640 break; 641 } 642 if (c == ' ' || c == '\t') 643 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 644 if (!c) { 645 *num = acc; 646 return 1; 647 } else 648 printf("%s is an invalid decimal number. Try again\n", 649 lbuf); 650 } 651 652 } 653 654 hex(str, num, deflt) 655 char *str; 656 int *num; 657 { 658 int acc = 0, c; 659 char *cp; 660 661 while (1) { 662 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 663 fgets(lbuf, LBUF, stdin); 664 lbuf[strlen(lbuf)-1] = 0; 665 666 if (!*lbuf) 667 return 0; 668 669 cp = lbuf; 670 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 671 if (!c) 672 return 0; 673 while (c = *cp++) { 674 if (c <= '9' && c >= '0') 675 acc = (acc << 4) + c - '0'; 676 else if (c <= 'f' && c >= 'a') 677 acc = (acc << 4) + c - 'a' + 10; 678 else if (c <= 'F' && c >= 'A') 679 acc = (acc << 4) + c - 'A' + 10; 680 else 681 break; 682 } 683 if (c == ' ' || c == '\t') 684 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 685 if (!c) { 686 *num = acc; 687 return 1; 688 } else 689 printf("%s is an invalid hex number. Try again\n", 690 lbuf); 691 } 692 693 } 694 695 string(str, ans) 696 char *str; 697 char **ans; 698 { 699 int c; 700 char *cp = lbuf; 701 702 while (1) { 703 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 704 fgets(lbuf, LBUF, stdin); 705 lbuf[strlen(lbuf)-1] = 0; 706 707 if (!*lbuf) 708 return 0; 709 710 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 711 if (c == '"') { 712 c = *++cp; 713 *ans = cp; 714 while ((c = *cp) && c != '"') cp++; 715 } else { 716 *ans = cp; 717 while ((c = *cp) && c != ' ' && c != '\t') cp++; 718 } 719 720 if (c) 721 *cp = 0; 722 return 1; 723 } 724 } 725 726 char *get_type(type) 727 int type; 728 { 729 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 730 int counter = 0; 731 struct part_type *ptr = part_types; 732 733 734 while(counter < numentries) 735 { 736 if(ptr->type == type) 737 { 738 return(ptr->name); 739 } 740 ptr++; 741 counter++; 742 } 743 return("unknown"); 744 } 745