fdisk.c revision 16561
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 37int iotest; 38 39#define LBUF 100 40static 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 59const char *disk; 60const char *disks[] = 61{ 62 "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 63}; 64 65char *name; 66 67struct disklabel disklabel; /* disk parameters */ 68 69int cyls, sectors, heads, cylsecs, disksecs; 70 71struct 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}; 78struct mboot mboot; 79 80#define ACTIVE 0x80 81#define BOOT_MAGIC 0xAA55 82 83int dos_cyls; 84int dos_heads; 85int dos_sectors; 86int dos_cylsecs; 87 88#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 89#define DOSCYL(c) (c & 0xff) 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 179static void print_s0(int which); 180static void print_part(int i); 181static void init_sector0(unsigned long start); 182static void change_part(int i); 183static void print_params(); 184static void change_active(int which); 185static void get_params_to_use(); 186static void dos(int sec, unsigned char *c, unsigned char *s, unsigned char *h); 187static int open_disk(int u_flag); 188static ssize_t read_disk(off_t sector, void *buf); 189static ssize_t write_disk(off_t sector, void *buf); 190static int get_params(); 191static int read_s0(); 192static int write_s0(); 193static int ok(char *str); 194static int decimal(char *str, int *num, int deflt); 195static char *get_type(int type); 196#if 0 197static int hex(char *str, int *num, int deflt); 198static int string(char *str, char **ans); 199#endif 200 201 202int 203main(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 316usage: 317 printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n"); 318 return(1); 319} 320 321static void 322print_s0(int which) 323{ 324int 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 335static struct dos_partition mtpart = { 0 }; 336 337static void 338print_part(int i) 339{ 340struct 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 361static void 362init_sector0(unsigned long start) 363{ 364struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 365unsigned 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 379static void 380change_part(int i) 381{ 382struct 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 438static void 439print_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 451static void 452change_active(int which) 453{ 454int i; 455int active = 3, tmp; 456struct 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 471void 472get_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\***********************************************/ 493static void 494dos(sec, c, s, h) 495int sec; 496unsigned char *c, *s, *h; 497{ 498int cy; 499int 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 517int fd; 518 519 /* Getting device status */ 520 521static int 522open_disk(int u_flag) 523{ 524struct 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 548static ssize_t 549read_disk(off_t sector, void *buf) 550{ 551 lseek(fd,(sector * 512), 0); 552 return read(fd, buf, 512); 553} 554 555static ssize_t 556write_disk(off_t sector, void *buf) 557{ 558 lseek(fd,(sector * 512), 0); 559 return write(fd, buf, 512); 560} 561 562static int 563get_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 588static int 589read_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 604static int 605write_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 636static int 637ok(str) 638char *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 652static int 653decimal(char *str, int *num, int deflt) 654{ 655int acc = 0, c; 656char *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 689static int 690hex(char *str, int *num, int deflt) 691{ 692int acc = 0, c; 693char *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 729static int 730string(char *str, char **ans) 731{ 732int c; 733char *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 760static char * 761get_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