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