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