fdisk.c revision 2810
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 do 395 Decimal("active partition", active, tmp); 396 while(!ok("Are you happy with this choice")); 397 } 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 cy = sec / ( dos_cylsecs ); 433 sec = sec - cy * ( dos_cylsecs ); 434 435 hd = sec / dos_sectors; 436 sec = (sec - hd * dos_sectors) + 1; 437 438 *h = hd; 439 *c = cy & 0xff; 440 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 441} 442 443int fd; 444 445 /* Getting device status */ 446 447open_disk(u_flag) 448{ 449struct stat st; 450 451 if (stat(disk, &st) == -1) { 452 fprintf(stderr, "%s: Can't get file status of %s\n", 453 name, disk); 454 return -1; 455 } 456 if ( !(st.st_mode & S_IFCHR) ) 457 fprintf(stderr,"%s: Device %s is not character special\n", 458 name, disk); 459 if ((fd = open(disk, u_flag?O_RDWR:O_RDONLY)) == -1) { 460 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 461 return -1; 462 } 463 if (get_params(0) == -1) { 464 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 465 name, disk); 466 return -1; 467 } 468 return fd; 469} 470 471 472read_disk(sector, buf) 473{ 474 lseek(fd,(sector * 512), 0); 475 return read(fd, buf, 512); 476} 477 478write_disk(sector, buf) 479{ 480 lseek(fd,(sector * 512), 0); 481 return write(fd, buf, 512); 482} 483 484get_params(verbose) 485{ 486 487 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 488 fprintf(stderr, 489 "%s: Can't get disk parameters on %s; supplying dummy ones\n", 490 name, disk); 491 dos_cyls = cyls = 1; 492 dos_heads = heads = 1; 493 dos_sectors = sectors = 1; 494 dos_cylsecs = cylsecs = heads * sectors; 495 disksecs = cyls * heads * sectors; 496 return disksecs; 497 } 498 499 dos_cyls = cyls = disklabel.d_ncylinders; 500 dos_heads = heads = disklabel.d_ntracks; 501 dos_sectors = sectors = disklabel.d_nsectors; 502 dos_cylsecs = cylsecs = heads * sectors; 503 disksecs = cyls * heads * sectors; 504 505 return (disksecs); 506} 507 508 509read_s0() 510{ 511 if (read_disk(0, (char *) mboot.bootinst) == -1) { 512 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 513 return -1; 514 } 515 if (mboot.signature != BOOT_MAGIC) { 516 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 517 name); 518 /* So should we initialize things */ 519 return -1; 520 } 521 return 0; 522} 523 524write_s0() 525{ 526 int flag; 527 if (iotest) { 528 print_s0(-1); 529 return 0; 530 } 531 /* 532 * write enable label sector before write (if necessary), 533 * disable after writing. 534 * needed if the disklabel protected area also protects 535 * sector 0. (e.g. empty disk) 536 */ 537 flag = 1; 538 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 539 perror("ioctl DIOCWLABEL"); 540 if (write_disk(0, (char *) mboot.bootinst) == -1) { 541 fprintf(stderr, "%s: Can't write fdisk partition table\n", 542 name); 543 return -1; 544 flag = 0; 545 (void) ioctl(fd, DIOCWLABEL, &flag); 546 } 547} 548 549 550 551ok(str) 552char *str; 553{ 554 printf("%s [n] ", str); 555 fgets(lbuf, LBUF, stdin); 556 lbuf[strlen(lbuf)-1] = 0; 557 558 if (*lbuf && 559 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 560 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 561 return 1; 562 else 563 return 0; 564} 565 566decimal(str, num, deflt) 567char *str; 568int *num; 569{ 570int acc = 0, c; 571char *cp; 572 573 while (1) { 574 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 575 fgets(lbuf, LBUF, stdin); 576 lbuf[strlen(lbuf)-1] = 0; 577 578 if (!*lbuf) 579 return 0; 580 581 cp = lbuf; 582 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 583 if (!c) 584 return 0; 585 while (c = *cp++) { 586 if (c <= '9' && c >= '0') 587 acc = acc * 10 + c - '0'; 588 else 589 break; 590 } 591 if (c == ' ' || c == '\t') 592 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 593 if (!c) { 594 *num = acc; 595 return 1; 596 } else 597 printf("%s is an invalid decimal number. Try again\n", 598 lbuf); 599 } 600 601} 602 603hex(str, num, deflt) 604char *str; 605int *num; 606{ 607int acc = 0, c; 608char *cp; 609 610 while (1) { 611 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 612 fgets(lbuf, LBUF, stdin); 613 lbuf[strlen(lbuf)-1] = 0; 614 615 if (!*lbuf) 616 return 0; 617 618 cp = lbuf; 619 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 620 if (!c) 621 return 0; 622 while (c = *cp++) { 623 if (c <= '9' && c >= '0') 624 acc = (acc << 4) + c - '0'; 625 else if (c <= 'f' && c >= 'a') 626 acc = (acc << 4) + c - 'a' + 10; 627 else if (c <= 'F' && c >= 'A') 628 acc = (acc << 4) + c - 'A' + 10; 629 else 630 break; 631 } 632 if (c == ' ' || c == '\t') 633 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 634 if (!c) { 635 *num = acc; 636 return 1; 637 } else 638 printf("%s is an invalid hex number. Try again\n", 639 lbuf); 640 } 641 642} 643 644string(str, ans) 645char *str; 646char **ans; 647{ 648int c; 649char *cp = lbuf; 650 651 while (1) { 652 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 653 fgets(lbuf, LBUF, stdin); 654 lbuf[strlen(lbuf)-1] = 0; 655 656 if (!*lbuf) 657 return 0; 658 659 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 660 if (c == '"') { 661 c = *++cp; 662 *ans = cp; 663 while ((c = *cp) && c != '"') cp++; 664 } else { 665 *ans = cp; 666 while ((c = *cp) && c != ' ' && c != '\t') cp++; 667 } 668 669 if (c) 670 *cp = 0; 671 return 1; 672 } 673} 674 675char *get_type(type) 676int type; 677{ 678 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 679 int counter = 0; 680 struct part_type *ptr = part_types; 681 682 683 while(counter < numentries) 684 { 685 if(ptr->type == type) 686 { 687 return(ptr->name); 688 } 689 ptr++; 690 counter++; 691 } 692 return("unknown"); 693} 694