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