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