fdisk.c revision 10514
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 35int iotest; 36 37#define LBUF 100 38static 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 57const char *disk; 58const char *disks[] = 59{ 60 "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 61}; 62 63char *name; 64 65struct disklabel disklabel; /* disk parameters */ 66 67int cyls, sectors, heads, cylsecs, disksecs; 68 69struct 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}; 76struct mboot mboot; 77 78#define ACTIVE 0x80 79#define BOOT_MAGIC 0xAA55 80 81int dos_cyls; 82int dos_heads; 83int dos_sectors; 84int dos_cylsecs; 85 86#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 87#define DOSCYL(c) (c & 0xff) 88static int dos(); 89char *get_type(); 90static int partition = -1; 91 92 93static int a_flag = 0; /* set active partition */ 94static int i_flag = 0; /* replace partition data */ 95static int u_flag = 0; /* update partition data */ 96 97static unsigned char bootcode[] = { 980x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 990x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 1000xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 1010x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 1020x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 1030x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 1040x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 1050x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 1060xeb, 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 131struct 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 180main(argc, argv) 181char **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 294usage: 295 printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n"); 296} 297 298print_s0(which) 299{ 300int 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 311static struct dos_partition mtpart = { 0 }; 312 313print_part(i) 314{ 315struct 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 336init_sector0(start) 337{ 338struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 339int size = disksecs - start; 340int 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 354change_part(i) 355{ 356struct 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 412print_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 424change_active(which) 425{ 426int i; 427int active = 3, tmp; 428struct 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 443get_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\***********************************************/ 464static 465dos(sec, c, s, h) 466int sec; 467unsigned char *c, *s, *h; 468{ 469int cy; 470int 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 488int fd; 489 490 /* Getting device status */ 491 492open_disk(u_flag) 493{ 494struct 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 519read_disk(sector, buf) 520{ 521 lseek(fd,(sector * 512), 0); 522 return read(fd, buf, 512); 523} 524 525write_disk(sector, buf) 526{ 527 lseek(fd,(sector * 512), 0); 528 return write(fd, buf, 512); 529} 530 531get_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 556read_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 571write_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 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 586 perror("ioctl DIOCWLABEL"); 587 if (write_disk(0, (char *) mboot.bootinst) == -1) { 588 fprintf(stderr, "%s: Can't write fdisk partition table\n", 589 name); 590 return -1; 591 flag = 0; 592 (void) ioctl(fd, DIOCWLABEL, &flag); 593 } 594} 595 596 597 598ok(str) 599char *str; 600{ 601 printf("%s [n] ", str); 602 fgets(lbuf, LBUF, stdin); 603 lbuf[strlen(lbuf)-1] = 0; 604 605 if (*lbuf && 606 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 607 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 608 return 1; 609 else 610 return 0; 611} 612 613decimal(str, num, deflt) 614char *str; 615int *num; 616{ 617int acc = 0, c; 618char *cp; 619 620 while (1) { 621 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 622 fgets(lbuf, LBUF, stdin); 623 lbuf[strlen(lbuf)-1] = 0; 624 625 if (!*lbuf) 626 return 0; 627 628 cp = lbuf; 629 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 630 if (!c) 631 return 0; 632 while (c = *cp++) { 633 if (c <= '9' && c >= '0') 634 acc = acc * 10 + c - '0'; 635 else 636 break; 637 } 638 if (c == ' ' || c == '\t') 639 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 640 if (!c) { 641 *num = acc; 642 return 1; 643 } else 644 printf("%s is an invalid decimal number. Try again\n", 645 lbuf); 646 } 647 648} 649 650hex(str, num, deflt) 651char *str; 652int *num; 653{ 654int acc = 0, c; 655char *cp; 656 657 while (1) { 658 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 659 fgets(lbuf, LBUF, stdin); 660 lbuf[strlen(lbuf)-1] = 0; 661 662 if (!*lbuf) 663 return 0; 664 665 cp = lbuf; 666 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 667 if (!c) 668 return 0; 669 while (c = *cp++) { 670 if (c <= '9' && c >= '0') 671 acc = (acc << 4) + c - '0'; 672 else if (c <= 'f' && c >= 'a') 673 acc = (acc << 4) + c - 'a' + 10; 674 else if (c <= 'F' && c >= 'A') 675 acc = (acc << 4) + c - 'A' + 10; 676 else 677 break; 678 } 679 if (c == ' ' || c == '\t') 680 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 681 if (!c) { 682 *num = acc; 683 return 1; 684 } else 685 printf("%s is an invalid hex number. Try again\n", 686 lbuf); 687 } 688 689} 690 691string(str, ans) 692char *str; 693char **ans; 694{ 695int c; 696char *cp = lbuf; 697 698 while (1) { 699 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 700 fgets(lbuf, LBUF, stdin); 701 lbuf[strlen(lbuf)-1] = 0; 702 703 if (!*lbuf) 704 return 0; 705 706 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 707 if (c == '"') { 708 c = *++cp; 709 *ans = cp; 710 while ((c = *cp) && c != '"') cp++; 711 } else { 712 *ans = cp; 713 while ((c = *cp) && c != ' ' && c != '\t') cp++; 714 } 715 716 if (c) 717 *cp = 0; 718 return 1; 719 } 720} 721 722char *get_type(type) 723int type; 724{ 725 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 726 int counter = 0; 727 struct part_type *ptr = part_types; 728 729 730 while(counter < numentries) 731 { 732 if(ptr->type == type) 733 { 734 return(ptr->name); 735 } 736 ptr++; 737 counter++; 738 } 739 return("unknown"); 740} 741