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 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 404 get_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 \***********************************************/ 425 static 426 dos(sec, c, s, h) 427 int sec; 428 unsigned char *c, *s, *h; 429 { 430 int cy; 431 int 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 449 int fd; 450 451 /* Getting device status */ 452 453 open_disk(u_flag) 454 { 455 struct 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 478 read_disk(sector, buf) 479 { 480 lseek(fd,(sector * 512), 0); 481 return read(fd, buf, 512); 482 } 483 484 write_disk(sector, buf) 485 { 486 lseek(fd,(sector * 512), 0); 487 return write(fd, buf, 512); 488 } 489 490 get_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 515 read_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 530 write_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 557 ok(str) 558 char *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 572 decimal(str, num, deflt) 573 char *str; 574 int *num; 575 { 576 int acc = 0, c; 577 char *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 609 hex(str, num, deflt) 610 char *str; 611 int *num; 612 { 613 int acc = 0, c; 614 char *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 650 string(str, ans) 651 char *str; 652 char **ans; 653 { 654 int c; 655 char *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 681 char *get_type(type) 682 int 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