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 34 int iotest; 35 36 #define LBUF 100 37 static 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 56 char *disk = "/dev/rwd0d"; 57 char *name; 58 59 struct disklabel disklabel; /* disk parameters */ 60 61 int cyls, sectors, heads, cylsecs, disksecs; 62 63 struct 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 }; 70 struct mboot mboot; 71 72 #define ACTIVE 0x80 73 #define BOOT_MAGIC 0xAA55 74 75 int dos_cyls; 76 int dos_heads; 77 int dos_sectors; 78 int dos_cylsecs; 79 80 #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 81 #define DOSCYL(c) (c & 0xff) 82 static int dos(); 83 char *get_type(); 84 static int partition = -1; 85 86 87 static int a_flag = 0; /* set active partition */ 88 static int i_flag = 0; /* replace partition data */ 89 static int u_flag = 0; /* update partition data */ 90 91 static unsigned char bootcode[] = { 92 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 93 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 94 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 95 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 96 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 97 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 98 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 99 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 100 0xeb, 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 125 struct 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 172 main(argc, argv) 173 char **argv; 174 { 175 int 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 255 usage: 256 printf("fdisk {-a|-i|-r} {disk}\n"); 257 } 258 259 print_s0(which) 260 { 261 int 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 272 static struct dos_partition mtpart = { 0 }; 273 274 print_part(i) 275 { 276 struct 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 297 init_sector0(start) 298 { 299 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 300 int size = disksecs - start; 301 int 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 315 change_part(i) 316 { 317 struct 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 373 print_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 385 change_active(which) 386 { 387 int i; 388 int active = 3, tmp; 389 struct 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 403 get_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 \***********************************************/ 424 static 425 dos(sec, c, s, h) 426 int sec; 427 unsigned char *c, *s, *h; 428 { 429 int cy; 430 int 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 443 int fd; 444 445 /* Getting device status */ 446 447 open_disk(u_flag) 448 { 449 struct 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 } else if ( !(st.st_mode & S_IFCHR) ) { 456 fprintf(stderr,"%s: Device %s is not character special\n", 457 name, disk); 458 return -1; 459 } 460 if ((fd = open(disk, u_flag?O_RDWR:O_RDONLY)) == -1) { 461 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 462 return -1; 463 } 464 if (get_params(0) == -1) { 465 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 466 name, disk); 467 return -1; 468 } 469 return fd; 470 } 471 472 473 read_disk(sector, buf) 474 { 475 lseek(fd,(sector * 512), 0); 476 return read(fd, buf, 512); 477 } 478 479 write_disk(sector, buf) 480 { 481 lseek(fd,(sector * 512), 0); 482 return write(fd, buf, 512); 483 } 484 485 get_params(verbose) 486 { 487 488 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 489 return -1; 490 } 491 492 dos_cyls = cyls = disklabel.d_ncylinders; 493 dos_heads = heads = disklabel.d_ntracks; 494 dos_sectors = sectors = disklabel.d_nsectors; 495 dos_cylsecs = cylsecs = heads * sectors; 496 disksecs = cyls * heads * sectors; 497 498 return (disksecs); 499 } 500 501 502 read_s0() 503 { 504 if (read_disk(0, (char *) mboot.bootinst) == -1) { 505 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 506 return -1; 507 } 508 if (mboot.signature != BOOT_MAGIC) { 509 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 510 name); 511 /* So should we initialize things */ 512 return -1; 513 } 514 return 0; 515 } 516 517 write_s0() 518 { 519 int flag; 520 if (iotest) { 521 print_s0(-1); 522 return 0; 523 } 524 /* 525 * write enable label sector before write (if necessary), 526 * disable after writing. 527 * needed if the disklabel protected area also protects 528 * sector 0. (e.g. empty disk) 529 */ 530 flag = 1; 531 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 532 perror("ioctl DIOCWLABEL"); 533 if (write_disk(0, (char *) mboot.bootinst) == -1) { 534 fprintf(stderr, "%s: Can't write fdisk partition table\n", 535 name); 536 return -1; 537 flag = 0; 538 (void) ioctl(fd, DIOCWLABEL, &flag); 539 } 540 } 541 542 543 544 ok(str) 545 char *str; 546 { 547 printf("%s [n] ", str); 548 fgets(lbuf, LBUF, stdin); 549 lbuf[strlen(lbuf)-1] = 0; 550 551 if (*lbuf && 552 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 553 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 554 return 1; 555 else 556 return 0; 557 } 558 559 decimal(str, num, deflt) 560 char *str; 561 int *num; 562 { 563 int acc = 0, c; 564 char *cp; 565 566 while (1) { 567 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 568 fgets(lbuf, LBUF, stdin); 569 lbuf[strlen(lbuf)-1] = 0; 570 571 if (!*lbuf) 572 return 0; 573 574 cp = lbuf; 575 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 576 if (!c) 577 return 0; 578 while (c = *cp++) { 579 if (c <= '9' && c >= '0') 580 acc = acc * 10 + c - '0'; 581 else 582 break; 583 } 584 if (c == ' ' || c == '\t') 585 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 586 if (!c) { 587 *num = acc; 588 return 1; 589 } else 590 printf("%s is an invalid decimal number. Try again\n", 591 lbuf); 592 } 593 594 } 595 596 hex(str, num, deflt) 597 char *str; 598 int *num; 599 { 600 int acc = 0, c; 601 char *cp; 602 603 while (1) { 604 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 605 fgets(lbuf, LBUF, stdin); 606 lbuf[strlen(lbuf)-1] = 0; 607 608 if (!*lbuf) 609 return 0; 610 611 cp = lbuf; 612 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 613 if (!c) 614 return 0; 615 while (c = *cp++) { 616 if (c <= '9' && c >= '0') 617 acc = (acc << 4) + c - '0'; 618 else if (c <= 'f' && c >= 'a') 619 acc = (acc << 4) + c - 'a' + 10; 620 else if (c <= 'F' && c >= 'A') 621 acc = (acc << 4) + c - 'A' + 10; 622 else 623 break; 624 } 625 if (c == ' ' || c == '\t') 626 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 627 if (!c) { 628 *num = acc; 629 return 1; 630 } else 631 printf("%s is an invalid hex number. Try again\n", 632 lbuf); 633 } 634 635 } 636 637 string(str, ans) 638 char *str; 639 char **ans; 640 { 641 int c; 642 char *cp = lbuf; 643 644 while (1) { 645 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 646 fgets(lbuf, LBUF, stdin); 647 lbuf[strlen(lbuf)-1] = 0; 648 649 if (!*lbuf) 650 return 0; 651 652 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 653 if (c == '"') { 654 c = *++cp; 655 *ans = cp; 656 while ((c = *cp) && c != '"') cp++; 657 } else { 658 *ans = cp; 659 while ((c = *cp) && c != ' ' && c != '\t') cp++; 660 } 661 662 if (c) 663 *cp = 0; 664 return 1; 665 } 666 } 667 668 char *get_type(type) 669 int type; 670 { 671 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 672 int counter = 0; 673 struct part_type *ptr = part_types; 674 675 676 while(counter < numentries) 677 { 678 if(ptr->type == type) 679 { 680 return(ptr->name); 681 } 682 ptr++; 683 counter++; 684 } 685 return("unknown"); 686 } 687