fdisk.c revision 1.2 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 (at) 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 #ifndef lint
28 static char rcsid[] = "$Id: fdisk.c,v 1.2 1993/08/02 17:51:04 mycroft Exp $";
29 #endif /* not lint */
30
31 #include <sys/types.h>
32 #include <sys/disklabel.h>
33 #include <stdio.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <fcntl.h>
37
38 int iotest;
39
40 #define LBUF 100
41 static char lbuf[LBUF];
42
43 /*
44 *
45 * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992
46 *
47 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
48 * Copyright (c) 1989 Robert. V. Baron
49 * Created.
50 */
51
52 #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
53 #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
54 #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
55
56 #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
57
58 #define SECSIZE 512
59
60 char *disk = "/dev/rwd0d";
61 char *name;
62
63 struct disklabel disklabel; /* disk parameters */
64
65 int cyls, sectors, heads, cylsecs, disksecs;
66
67 struct mboot
68 {
69 unsigned char padding[2]; /* force the longs to be long alligned */
70 unsigned char bootinst[DOSPARTOFF];
71 struct dos_partition parts[4];
72 unsigned short int signature;
73 };
74 struct mboot mboot;
75
76 #define ACTIVE 0x80
77 #define BOOT_MAGIC 0xAA55
78
79 int dos_cyls;
80 int dos_heads;
81 int dos_sectors;
82 int dos_cylsecs;
83
84 #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
85 #define DOSCYL(c) (c & 0xff)
86 static int dos();
87 char *get_type();
88 static int partition = -1;
89
90
91 static int a_flag = 0; /* set active partition */
92 static int i_flag = 0; /* replace partition data */
93 static int u_flag = 0; /* update partition data */
94
95 static unsigned char bootcode[] = {
96 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
97 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
98 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
99 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
100 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
101 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
102 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
103 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
104 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
105 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
106 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
107 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
108 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
109 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
110 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
111 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
112 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
113
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, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
127 };
128
129 struct part_type
131 {
132 unsigned char type;
133 char *name;
134 }part_types[] =
135 {
136 {0x00, "unused"}
137 ,{0x01, "Primary DOS with 12 bit FAT"}
138 ,{0x02, "XENIX / filesystem"}
139 ,{0x03, "XENIX /usr filesystem"}
140 ,{0x04, "Primary DOS with 16 bit FAT"}
141 ,{0x05, "Extended DOS"}
142 ,{0x06, "Primary 'big' DOS (> 32MB)"}
143 ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
144 ,{0x08, "AIX filesystem"}
145 ,{0x09, "AIX boot partition or Coherent"}
146 ,{0x0A, "OS/2 Boot Manager or OPUS"}
147 ,{0x10, "OPUS"}
148 ,{0x40, "VENIX 286"}
149 ,{0x50, "DM"}
150 ,{0x51, "DM"}
151 ,{0x52, "CP/M or Microport SysV/AT"}
152 ,{0x56, "GB"}
153 ,{0x61, "Speed"}
154 ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
155 ,{0x64, "Novell Netware 2.xx"}
156 ,{0x65, "Novell Netware 3.xx"}
157 ,{0x75, "PCIX"}
158 ,{0x80, "Minix 1.1 ... 1.4a"}
159 ,{0x81, "Minix 1.4b ... 1.5.10"}
160 ,{0x82, "Linux"}
161 ,{0x93, "Amoeba filesystem"}
162 ,{0x94, "Amoeba bad block table"}
163 ,{0xA5, "386BSD"}
164 ,{0xB7, "BSDI BSD/386 filesystem"}
165 ,{0xB8, "BSDI BSD/386 swap"}
166 ,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
167 ,{0xE1, "Speed"}
168 ,{0xE3, "Speed"}
169 ,{0xE4, "Speed"}
170 ,{0xF1, "Speed"}
171 ,{0xF2, "DOS 3.3+ Secondary"}
172 ,{0xF4, "Speed"}
173 ,{0xFF, "BBT (Bad Blocks Table)"}
174 };
175
176
177 main(argc, argv)
178 char **argv;
179 {
180 int i;
181
182 name = *argv;
183 {register char *cp = name;
184 while (*cp) if (*cp++ == '/') name = cp;
185 }
186
187 for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
188 if (*token++ != '-' || !*token)
189 break;
190 else { register int flag;
191 for ( ; flag = *token++ ; ) {
192 switch (flag) {
193 case '0':
194 partition = 0;
195 break;
196 case '1':
197 partition = 1;
198 break;
199 case '2':
200 partition = 2;
201 break;
202 case '3':
203 partition = 3;
204 break;
205 case 'a':
206 a_flag = 1;
207 break;
208 case 'i':
209 i_flag = 1;
210 case 'u':
211 u_flag = 1;
212 break;
213 default:
214 goto usage;
215 }
216 }
217 }
218 }
219
220 if (argc > 0)
221 disk = argv[0];
222
223 if (open_disk(u_flag) < 0)
224 exit(1);
225
226 printf("******* Working on device %s *******\n",disk);
227 if(u_flag)
228 {
229 get_params_to_use();
230 }
231 else
232 {
233 print_params();
234 }
235
236 if (read_s0())
237 init_sector0(1);
238
239 printf("Warning: BIOS sector numbering starts with sector 1\n");
240 printf("Information from DOS bootblock is:\n");
241 if (partition == -1)
242 for (i = 0; i < NDOSPART; i++)
243 change_part(i);
244 else
245 change_part(partition);
246
247 if (u_flag || a_flag)
248 change_active(partition);
249
250 if (u_flag || a_flag) {
251 printf("\nWe haven't changed the partition table yet. ");
252 printf("This is your last chance.\n");
253 print_s0(-1);
254 if (ok("Should we write new partition table?"))
255 write_s0();
256 }
257
258 exit(0);
259
260 usage:
261 printf("fdisk {-a|-i|-r} {disk}\n");
262 }
263
264 print_s0(which)
265 {
266 int i;
267
268 print_params();
269 printf("Information from DOS bootblock is:\n");
270 if (which == -1)
271 for (i = 0; i < NDOSPART; i++)
272 printf("%d: ", i), print_part(i);
273 else
274 print_part(which);
275 }
276
277 static struct dos_partition mtpart = { 0 };
278
279 print_part(i)
280 {
281 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
282
283
284 if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
285 printf("<UNUSED>\n");
286 return;
287 }
288 printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
289 printf(" start %d, size %d (%d Meg), flag %x\n",
290 partp->dp_start,
291 partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
292 partp->dp_flag);
293 printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
294 ,DPCYL(partp->dp_scyl, partp->dp_ssect)
295 ,DPSECT(partp->dp_ssect)
296 ,partp->dp_shd
297 ,DPCYL(partp->dp_ecyl, partp->dp_esect)
298 ,DPSECT(partp->dp_esect)
299 ,partp->dp_ehd);
300 }
301
302 init_sector0(start)
303 {
304 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
305 int size = disksecs - start;
306 int rest;
307
308 memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
309 mboot.signature = BOOT_MAGIC;
310
311 partp->dp_typ = DOSPTYP_386BSD;
312 partp->dp_flag = ACTIVE;
313 partp->dp_start = start;
314 partp->dp_size = size;
315
316 dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
317 dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
318 }
319
320 change_part(i)
321 {
322 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
323
324 printf("The data for partition %d is:\n", i);
325 print_part(i);
326
327 if (u_flag && ok("Do you want to change it?")) {
328 int tmp;
329
330 if (i_flag) {
331 bzero((char *)partp, sizeof (struct dos_partition));
332 if (i == 3) {
333 init_sector0(1);
334 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
335 print_part(i);
336 }
337 }
338
339 do {
340 Decimal("sysid", partp->dp_typ, tmp);
341 Decimal("start", partp->dp_start, tmp);
342 Decimal("size", partp->dp_size, tmp);
343
344 if (ok("Explicitly specifiy beg/end address ?"))
345 {
346 int tsec,tcyl,thd;
347 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
348 thd = partp->dp_shd;
349 tsec = DPSECT(partp->dp_ssect);
350 Decimal("beginning cylinder", tcyl, tmp);
351 Decimal("beginning head", thd, tmp);
352 Decimal("beginning sector", tsec, tmp);
353 partp->dp_scyl = DOSCYL(tcyl);
354 partp->dp_ssect = DOSSECT(tsec,tcyl);
355 partp->dp_shd = thd;
356
357 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
358 thd = partp->dp_ehd;
359 tsec = DPSECT(partp->dp_esect);
360 Decimal("ending cylinder", tcyl, tmp);
361 Decimal("ending head", thd, tmp);
362 Decimal("ending sector", tsec, tmp);
363 partp->dp_ecyl = DOSCYL(tcyl);
364 partp->dp_esect = DOSSECT(tsec,tcyl);
365 partp->dp_ehd = thd;
366 } else {
367 dos(partp->dp_start,
368 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
369 dos(partp->dp_start+partp->dp_size - 1,
370 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
371 }
372
373 print_part(i);
374 } while (!ok("Are we happy with this entry?"));
375 }
376 }
377
378 print_params()
379 {
380 printf("parameters extracted from in-core disklabel are:\n");
381 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
382 ,cyls,heads,sectors,cylsecs);
383 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
384 printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
385 printf("parameters to be used for BIOS calculations are:\n");
386 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
387 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
388 }
389
390 change_active(which)
391 {
392 int i;
393 int active = 3, tmp;
394 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
395
396 if (a_flag && which != -1)
397 active = which;
398 if (ok("Do you want to change the active partition?")) {
399 do
400 Decimal("active partition", active, tmp);
401 while(!ok("Are you happy with this choice"));
402 }
403 for (i = 0; i < NDOSPART; i++)
404 partp[i].dp_flag = 0;
405 partp[active].dp_flag = ACTIVE;
406 }
407
408 get_params_to_use()
409 {
410 int tmp;
411 print_params();
412 if (ok("Do you want to change our idea of what BIOS thinks ?"))
413 {
414 do
415 {
416 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
417 Decimal("BIOS's idea of #heads", dos_heads, tmp);
418 Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
419 dos_cylsecs = dos_heads * dos_sectors;
420 print_params();
421 }
422 while(!ok("Are you happy with this choice"));
423 }
424 }
425
426 /***********************************************\
427 * Change real numbers into strange dos numbers *
428 \***********************************************/
429 static
430 dos(sec, c, s, h)
431 int sec;
432 unsigned char *c, *s, *h;
433 {
434 int cy;
435 int hd;
436
437 cy = sec / ( dos_cylsecs );
438 sec = sec - cy * ( dos_cylsecs );
439
440 hd = sec / dos_sectors;
441 sec = (sec - hd * dos_sectors) + 1;
442
443 *h = hd;
444 *c = cy & 0xff;
445 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
446 }
447
448 int fd;
449
450 /* Getting device status */
451
452 open_disk(u_flag)
453 {
454 struct stat st;
455
456 if (stat(disk, &st) == -1) {
457 fprintf(stderr, "%s: Can't get file status of %s\n",
458 name, disk);
459 return -1;
460 } else if ( !(st.st_mode & S_IFCHR) ) {
461 fprintf(stderr,"%s: Device %s is not character special\n",
462 name, disk);
463 return -1;
464 }
465 if ((fd = open(disk, 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 return -1;
495 }
496
497 dos_cyls = cyls = disklabel.d_ncylinders;
498 dos_heads = heads = disklabel.d_ntracks;
499 dos_sectors = sectors = disklabel.d_nsectors;
500 dos_cylsecs = cylsecs = heads * sectors;
501 disksecs = cyls * heads * sectors;
502
503 return (disksecs);
504 }
505
506
508 read_s0()
509 {
510 if (read_disk(0, (char *) mboot.bootinst) == -1) {
511 fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
512 return -1;
513 }
514 if (mboot.signature != BOOT_MAGIC) {
515 fprintf(stderr, "%s: Invalid fdisk partition table found\n",
516 name);
517 /* So should we initialize things */
518 return -1;
519 }
520 return 0;
521 }
522
523 write_s0()
524 {
525 int flag;
526 if (iotest) {
527 print_s0(-1);
528 return 0;
529 }
530 /*
531 * write enable label sector before write (if necessary),
532 * disable after writing.
533 * needed if the disklabel protected area also protects
534 * sector 0. (e.g. empty disk)
535 */
536 flag = 1;
537 if (ioctl(fd, DIOCWLABEL, &flag) < 0)
538 perror("ioctl DIOCWLABEL");
539 if (write_disk(0, (char *) mboot.bootinst) == -1) {
540 fprintf(stderr, "%s: Can't write fdisk partition table\n",
541 name);
542 return -1;
543 flag = 0;
544 (void) ioctl(fd, DIOCWLABEL, &flag);
545 }
546 }
547
548
549
550 ok(str)
551 char *str;
552 {
553 printf("%s [n] ", str);
554 fgets(lbuf, LBUF, stdin);
555 lbuf[strlen(lbuf)-1] = 0;
556
557 if (*lbuf &&
558 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
559 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
560 return 1;
561 else
562 return 0;
563 }
564
565 decimal(str, num, deflt)
566 char *str;
567 int *num;
568 {
569 int acc = 0, c;
570 char *cp;
571
572 while (1) {
573 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
574 fgets(lbuf, LBUF, stdin);
575 lbuf[strlen(lbuf)-1] = 0;
576
577 if (!*lbuf)
578 return 0;
579
580 cp = lbuf;
581 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
582 if (!c)
583 return 0;
584 while (c = *cp++) {
585 if (c <= '9' && c >= '0')
586 acc = acc * 10 + c - '0';
587 else
588 break;
589 }
590 if (c == ' ' || c == '\t')
591 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
592 if (!c) {
593 *num = acc;
594 return 1;
595 } else
596 printf("%s is an invalid decimal number. Try again\n",
597 lbuf);
598 }
599
600 }
601
602 hex(str, num, deflt)
603 char *str;
604 int *num;
605 {
606 int acc = 0, c;
607 char *cp;
608
609 while (1) {
610 printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
611 fgets(lbuf, LBUF, stdin);
612 lbuf[strlen(lbuf)-1] = 0;
613
614 if (!*lbuf)
615 return 0;
616
617 cp = lbuf;
618 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
619 if (!c)
620 return 0;
621 while (c = *cp++) {
622 if (c <= '9' && c >= '0')
623 acc = (acc << 4) + c - '0';
624 else if (c <= 'f' && c >= 'a')
625 acc = (acc << 4) + c - 'a' + 10;
626 else if (c <= 'F' && c >= 'A')
627 acc = (acc << 4) + c - 'A' + 10;
628 else
629 break;
630 }
631 if (c == ' ' || c == '\t')
632 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
633 if (!c) {
634 *num = acc;
635 return 1;
636 } else
637 printf("%s is an invalid hex number. Try again\n",
638 lbuf);
639 }
640
641 }
642
643 string(str, ans)
644 char *str;
645 char **ans;
646 {
647 int c;
648 char *cp = lbuf;
649
650 while (1) {
651 printf("Supply a string value for \"%s\" [%s] ", str, *ans);
652 fgets(lbuf, LBUF, stdin);
653 lbuf[strlen(lbuf)-1] = 0;
654
655 if (!*lbuf)
656 return 0;
657
658 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
659 if (c == '"') {
660 c = *++cp;
661 *ans = cp;
662 while ((c = *cp) && c != '"') cp++;
663 } else {
664 *ans = cp;
665 while ((c = *cp) && c != ' ' && c != '\t') cp++;
666 }
667
668 if (c)
669 *cp = 0;
670 return 1;
671 }
672 }
673
674 char *get_type(type)
675 int type;
676 {
677 int numentries = (sizeof(part_types)/sizeof(struct part_type));
678 int counter = 0;
679 struct part_type *ptr = part_types;
680
681
682 while(counter < numentries)
683 {
684 if(ptr->type == type)
685 {
686 return(ptr->name);
687 }
688 ptr++;
689 counter++;
690 }
691 return("unknown");
692 }
693