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 ,{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 174 main(argc, argv) 175 char **argv; 176 { 177 int 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 257 usage: 258 printf("fdisk {-a|-i|-r} {disk}\n"); 259 } 260 261 print_s0(which) 262 { 263 int 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 274 static struct dos_partition mtpart = { 0 }; 275 276 print_part(i) 277 { 278 struct 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 299 init_sector0(start) 300 { 301 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 302 int size = disksecs - start; 303 int 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 317 change_part(i) 318 { 319 struct 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 375 print_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 387 change_active(which) 388 { 389 int i; 390 int active = 3, tmp; 391 struct 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 406 get_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 \***********************************************/ 427 static 428 dos(sec, c, s, h) 429 int sec; 430 unsigned char *c, *s, *h; 431 { 432 int cy; 433 int 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 451 int fd; 452 453 /* Getting device status */ 454 455 open_disk(u_flag) 456 { 457 struct 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 480 read_disk(sector, buf) 481 { 482 lseek(fd,(sector * 512), 0); 483 return read(fd, buf, 512); 484 } 485 486 write_disk(sector, buf) 487 { 488 lseek(fd,(sector * 512), 0); 489 return write(fd, buf, 512); 490 } 491 492 get_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 517 read_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 532 write_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 559 ok(str) 560 char *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 574 decimal(str, num, deflt) 575 char *str; 576 int *num; 577 { 578 int acc = 0, c; 579 char *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 611 hex(str, num, deflt) 612 char *str; 613 int *num; 614 { 615 int acc = 0, c; 616 char *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 652 string(str, ans) 653 char *str; 654 char **ans; 655 { 656 int c; 657 char *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 683 char *get_type(type) 684 int 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