fdisk.c revision 8871
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 swap"} 156 ,{0x83, "Linux filesystem"} 157 ,{0x93, "Amoeba filesystem"} 158 ,{0x94, "Amoeba bad block table"} 159 ,{0xA5, "FreeBSD/NetBSD/386BSD"} 160 ,{0xA7, "NEXTSTEP"} 161 ,{0xB7, "BSDI BSD/386 filesystem"} 162 ,{0xB8, "BSDI BSD/386 swap"} 163 ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 164 ,{0xE1, "Speed"} 165 ,{0xE3, "Speed"} 166 ,{0xE4, "Speed"} 167 ,{0xF1, "Speed"} 168 ,{0xF2, "DOS 3.3+ Secondary"} 169 ,{0xF4, "Speed"} 170 ,{0xFF, "BBT (Bad Blocks Table)"} 171}; 172 173 174main(argc, argv) 175char **argv; 176{ 177int i; 178 179 name = *argv; 180 {register char *cp = name; 181 while (*cp) if (*cp++ == '/') name = cp; 182 } 183 184 for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 185 if (*token++ != '-' || !*token) 186 break; 187 else { register int flag; 188 for ( ; flag = *token++ ; ) { 189 switch (flag) { 190 case '0': 191 partition = 0; 192 break; 193 case '1': 194 partition = 1; 195 break; 196 case '2': 197 partition = 2; 198 break; 199 case '3': 200 partition = 3; 201 break; 202 case 'a': 203 a_flag = 1; 204 break; 205 case 'i': 206 i_flag = 1; 207 case 'u': 208 u_flag = 1; 209 break; 210 default: 211 goto usage; 212 } 213 } 214 } 215 } 216 217 if (argc > 0) 218 disk = argv[0]; 219 220 if (open_disk(u_flag) < 0) 221 exit(1); 222 223 printf("******* Working on device %s *******\n",disk); 224 if(u_flag) 225 { 226 get_params_to_use(); 227 } 228 else 229 { 230 print_params(); 231 } 232 233 if (read_s0()) 234 init_sector0(1); 235 236 printf("Warning: BIOS sector numbering starts with sector 1\n"); 237 printf("Information from DOS bootblock is:\n"); 238 if (partition == -1) 239 for (i = 0; i < NDOSPART; i++) 240 change_part(i); 241 else 242 change_part(partition); 243 244 if (u_flag || a_flag) 245 change_active(partition); 246 247 if (u_flag || a_flag) { 248 printf("\nWe haven't changed the partition table yet. "); 249 printf("This is your last chance.\n"); 250 print_s0(-1); 251 if (ok("Should we write new partition table?")) 252 write_s0(); 253 } 254 255 exit(0); 256 257usage: 258 printf("fdisk {-a|-i|-r} {disk}\n"); 259} 260 261print_s0(which) 262{ 263int i; 264 265 print_params(); 266 printf("Information from DOS bootblock is:\n"); 267 if (which == -1) 268 for (i = 0; i < NDOSPART; i++) 269 printf("%d: ", i), print_part(i); 270 else 271 print_part(which); 272} 273 274static struct dos_partition mtpart = { 0 }; 275 276print_part(i) 277{ 278struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 279 280 281 if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 282 printf("<UNUSED>\n"); 283 return; 284 } 285 printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 286 printf(" start %d, size %d (%d Meg), flag %x\n", 287 partp->dp_start, 288 partp->dp_size, partp->dp_size * 512 / (1024 * 1024), 289 partp->dp_flag); 290 printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 291 ,DPCYL(partp->dp_scyl, partp->dp_ssect) 292 ,DPSECT(partp->dp_ssect) 293 ,partp->dp_shd 294 ,DPCYL(partp->dp_ecyl, partp->dp_esect) 295 ,DPSECT(partp->dp_esect) 296 ,partp->dp_ehd); 297} 298 299init_sector0(start) 300{ 301struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 302int size = disksecs - start; 303int rest; 304 305 memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 306 mboot.signature = BOOT_MAGIC; 307 308 partp->dp_typ = DOSPTYP_386BSD; 309 partp->dp_flag = ACTIVE; 310 partp->dp_start = start; 311 partp->dp_size = size; 312 313 dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 314 dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 315} 316 317change_part(i) 318{ 319struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 320 321 printf("The data for partition %d is:\n", i); 322 print_part(i); 323 324 if (u_flag && ok("Do you want to change it?")) { 325 int tmp; 326 327 if (i_flag) { 328 bzero((char *)partp, sizeof (struct dos_partition)); 329 if (i == 3) { 330 init_sector0(1); 331 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); 332 print_part(i); 333 } 334 } 335 336 do { 337 Decimal("sysid", partp->dp_typ, tmp); 338 Decimal("start", partp->dp_start, tmp); 339 Decimal("size", partp->dp_size, tmp); 340 341 if (ok("Explicitly specifiy beg/end address ?")) 342 { 343 int tsec,tcyl,thd; 344 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 345 thd = partp->dp_shd; 346 tsec = DPSECT(partp->dp_ssect); 347 Decimal("beginning cylinder", tcyl, tmp); 348 Decimal("beginning head", thd, tmp); 349 Decimal("beginning sector", tsec, tmp); 350 partp->dp_scyl = DOSCYL(tcyl); 351 partp->dp_ssect = DOSSECT(tsec,tcyl); 352 partp->dp_shd = thd; 353 354 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 355 thd = partp->dp_ehd; 356 tsec = DPSECT(partp->dp_esect); 357 Decimal("ending cylinder", tcyl, tmp); 358 Decimal("ending head", thd, tmp); 359 Decimal("ending sector", tsec, tmp); 360 partp->dp_ecyl = DOSCYL(tcyl); 361 partp->dp_esect = DOSSECT(tsec,tcyl); 362 partp->dp_ehd = thd; 363 } else { 364 dos(partp->dp_start, 365 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 366 dos(partp->dp_start+partp->dp_size - 1, 367 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 368 } 369 370 print_part(i); 371 } while (!ok("Are we happy with this entry?")); 372 } 373} 374 375print_params() 376{ 377 printf("parameters extracted from in-core disklabel are:\n"); 378 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 379 ,cyls,heads,sectors,cylsecs); 380 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 381 printf(" Figures below won't work with BIOS for partitions not in cyl 1\n"); 382 printf("parameters to be used for BIOS calculations are:\n"); 383 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 384 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 385} 386 387change_active(which) 388{ 389int i; 390int active = 3, tmp; 391struct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 392 393 if (a_flag && which != -1) 394 active = which; 395 if (!ok("Do you want to change the active partition?")) 396 return; 397 do 398 Decimal("active partition", active, tmp); 399 while (!ok("Are you happy with this choice")); 400 for (i = 0; i < NDOSPART; i++) 401 partp[i].dp_flag = 0; 402 if (active >= 0 && active < NDOSPART) 403 partp[active].dp_flag = ACTIVE; 404} 405 406get_params_to_use() 407{ 408 int tmp; 409 print_params(); 410 if (ok("Do you want to change our idea of what BIOS thinks ?")) 411 { 412 do 413 { 414 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 415 Decimal("BIOS's idea of #heads", dos_heads, tmp); 416 Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 417 dos_cylsecs = dos_heads * dos_sectors; 418 print_params(); 419 } 420 while(!ok("Are you happy with this choice")); 421 } 422} 423 424/***********************************************\ 425* Change real numbers into strange dos numbers * 426\***********************************************/ 427static 428dos(sec, c, s, h) 429int sec; 430unsigned char *c, *s, *h; 431{ 432int cy; 433int hd; 434 435 if (sec == 0) { 436 *s = *c = *h = 0; 437 return; 438 } 439 440 cy = sec / ( dos_cylsecs ); 441 sec = sec - cy * ( dos_cylsecs ); 442 443 hd = sec / dos_sectors; 444 sec = (sec - hd * dos_sectors) + 1; 445 446 *h = hd; 447 *c = cy & 0xff; 448 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 449} 450 451int fd; 452 453 /* Getting device status */ 454 455open_disk(u_flag) 456{ 457struct stat st; 458 459 if (stat(disk, &st) == -1) { 460 fprintf(stderr, "%s: Can't get file status of %s\n", 461 name, disk); 462 return -1; 463 } 464 if ( !(st.st_mode & S_IFCHR) ) 465 fprintf(stderr,"%s: Device %s is not character special\n", 466 name, disk); 467 if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 468 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 469 return -1; 470 } 471 if (get_params(0) == -1) { 472 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 473 name, disk); 474 return -1; 475 } 476 return fd; 477} 478 479 480read_disk(sector, buf) 481{ 482 lseek(fd,(sector * 512), 0); 483 return read(fd, buf, 512); 484} 485 486write_disk(sector, buf) 487{ 488 lseek(fd,(sector * 512), 0); 489 return write(fd, buf, 512); 490} 491 492get_params(verbose) 493{ 494 495 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 496 fprintf(stderr, 497 "%s: Can't get disk parameters on %s; supplying dummy ones\n", 498 name, disk); 499 dos_cyls = cyls = 1; 500 dos_heads = heads = 1; 501 dos_sectors = sectors = 1; 502 dos_cylsecs = cylsecs = heads * sectors; 503 disksecs = cyls * heads * sectors; 504 return disksecs; 505 } 506 507 dos_cyls = cyls = disklabel.d_ncylinders; 508 dos_heads = heads = disklabel.d_ntracks; 509 dos_sectors = sectors = disklabel.d_nsectors; 510 dos_cylsecs = cylsecs = heads * sectors; 511 disksecs = cyls * heads * sectors; 512 513 return (disksecs); 514} 515 516 517read_s0() 518{ 519 if (read_disk(0, (char *) mboot.bootinst) == -1) { 520 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 521 return -1; 522 } 523 if (mboot.signature != BOOT_MAGIC) { 524 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 525 name); 526 /* So should we initialize things */ 527 return -1; 528 } 529 return 0; 530} 531 532write_s0() 533{ 534 int flag; 535 if (iotest) { 536 print_s0(-1); 537 return 0; 538 } 539 /* 540 * write enable label sector before write (if necessary), 541 * disable after writing. 542 * needed if the disklabel protected area also protects 543 * sector 0. (e.g. empty disk) 544 */ 545 flag = 1; 546 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 547 perror("ioctl DIOCWLABEL"); 548 if (write_disk(0, (char *) mboot.bootinst) == -1) { 549 fprintf(stderr, "%s: Can't write fdisk partition table\n", 550 name); 551 return -1; 552 flag = 0; 553 (void) ioctl(fd, DIOCWLABEL, &flag); 554 } 555} 556 557 558 559ok(str) 560char *str; 561{ 562 printf("%s [n] ", str); 563 fgets(lbuf, LBUF, stdin); 564 lbuf[strlen(lbuf)-1] = 0; 565 566 if (*lbuf && 567 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 568 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 569 return 1; 570 else 571 return 0; 572} 573 574decimal(str, num, deflt) 575char *str; 576int *num; 577{ 578int acc = 0, c; 579char *cp; 580 581 while (1) { 582 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 583 fgets(lbuf, LBUF, stdin); 584 lbuf[strlen(lbuf)-1] = 0; 585 586 if (!*lbuf) 587 return 0; 588 589 cp = lbuf; 590 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 591 if (!c) 592 return 0; 593 while (c = *cp++) { 594 if (c <= '9' && c >= '0') 595 acc = acc * 10 + c - '0'; 596 else 597 break; 598 } 599 if (c == ' ' || c == '\t') 600 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 601 if (!c) { 602 *num = acc; 603 return 1; 604 } else 605 printf("%s is an invalid decimal number. Try again\n", 606 lbuf); 607 } 608 609} 610 611hex(str, num, deflt) 612char *str; 613int *num; 614{ 615int acc = 0, c; 616char *cp; 617 618 while (1) { 619 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 620 fgets(lbuf, LBUF, stdin); 621 lbuf[strlen(lbuf)-1] = 0; 622 623 if (!*lbuf) 624 return 0; 625 626 cp = lbuf; 627 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 628 if (!c) 629 return 0; 630 while (c = *cp++) { 631 if (c <= '9' && c >= '0') 632 acc = (acc << 4) + c - '0'; 633 else if (c <= 'f' && c >= 'a') 634 acc = (acc << 4) + c - 'a' + 10; 635 else if (c <= 'F' && c >= 'A') 636 acc = (acc << 4) + c - 'A' + 10; 637 else 638 break; 639 } 640 if (c == ' ' || c == '\t') 641 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 642 if (!c) { 643 *num = acc; 644 return 1; 645 } else 646 printf("%s is an invalid hex number. Try again\n", 647 lbuf); 648 } 649 650} 651 652string(str, ans) 653char *str; 654char **ans; 655{ 656int c; 657char *cp = lbuf; 658 659 while (1) { 660 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 661 fgets(lbuf, LBUF, stdin); 662 lbuf[strlen(lbuf)-1] = 0; 663 664 if (!*lbuf) 665 return 0; 666 667 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 668 if (c == '"') { 669 c = *++cp; 670 *ans = cp; 671 while ((c = *cp) && c != '"') cp++; 672 } else { 673 *ans = cp; 674 while ((c = *cp) && c != ' ' && c != '\t') cp++; 675 } 676 677 if (c) 678 *cp = 0; 679 return 1; 680 } 681} 682 683char *get_type(type) 684int type; 685{ 686 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 687 int counter = 0; 688 struct part_type *ptr = part_types; 689 690 691 while(counter < numentries) 692 { 693 if(ptr->type == type) 694 { 695 return(ptr->name); 696 } 697 ptr++; 698 counter++; 699 } 700 return("unknown"); 701} 702