fdisk.c revision 36262
1219019Sgabor/*
2219019Sgabor * Mach Operating System
3219019Sgabor * Copyright (c) 1992 Carnegie Mellon University
4219019Sgabor * All Rights Reserved.
5219019Sgabor *
6219019Sgabor * Permission to use, copy, modify and distribute this software and its
7219019Sgabor * documentation is hereby granted, provided that both the copyright
8219019Sgabor * notice and this permission notice appear in all copies of the
9219019Sgabor * software, derivative works or modified versions, and any portions
10219019Sgabor * thereof, and that both notices appear in supporting documentation.
11219019Sgabor *
12219019Sgabor * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13219019Sgabor * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14219019Sgabor * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15219019Sgabor *
16219019Sgabor * Carnegie Mellon requests users of this software to return to
17219019Sgabor *
18219019Sgabor *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19219019Sgabor *  School of Computer Science
20219019Sgabor *  Carnegie Mellon University
21219019Sgabor *  Pittsburgh PA 15213-3890
22219019Sgabor *
23219019Sgabor * any improvements or extensions that they make and grant Carnegie Mellon
24219019Sgabor * the rights to redistribute these changes.
25219019Sgabor */
26219019Sgabor
27219019Sgabor#include <sys/types.h>
28219019Sgabor#include <sys/disklabel.h>
29219019Sgabor#include <stdio.h>
30219019Sgabor#include <string.h>
31219019Sgabor#include <errno.h>
32219019Sgabor#include <sys/stat.h>
33219019Sgabor#include <sys/ioctl.h>
34219019Sgabor#include <fcntl.h>
35219019Sgabor#include <unistd.h>
36219019Sgabor
37219019Sgaborint iotest;
38219019Sgabor
39219019Sgabor#define LBUF 100
40219019Sgaborstatic char lbuf[LBUF];
41219019Sgabor
42219019Sgabor/*
43219019Sgabor *
44219019Sgabor * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
45219019Sgabor *
46219019Sgabor * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
47219019Sgabor *	Copyright (c) 1989	Robert. V. Baron
48219019Sgabor *	Created.
49219019Sgabor */
50219019Sgabor
51219019Sgabor#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
52219019Sgabor#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
53219019Sgabor#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
54219019Sgabor
55219019Sgabor#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
56219019Sgabor
57219019Sgabor#define MAX_SEC_SIZE 2048	/* maximum section size that is supported */
58219019Sgabor#define MIN_SEC_SIZE 512	/* the sector size to start sensing at */
59219019Sgaborint secsize = 0;		/* the sensed sector size */
60219019Sgabor
61219019Sgaborconst char *disk;
62219019Sgaborconst char *disks[] =
63219019Sgabor{
64219019Sgabor  "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0
65219019Sgabor};
66219019Sgabor
67219019Sgaborchar *name;
68219019Sgabor
69219019Sgaborstruct disklabel disklabel;		/* disk parameters */
70219019Sgabor
71219019Sgaborint cyls, sectors, heads, cylsecs, disksecs;
72219019Sgabor
73219019Sgaborstruct mboot
74219019Sgabor{
75219019Sgabor	unsigned char padding[2]; /* force the longs to be long alligned */
76219019Sgabor	unsigned char bootinst[DOSPARTOFF];
77219019Sgabor	struct	dos_partition parts[4];
78219019Sgabor	unsigned short int	signature;
79219019Sgabor	/* room to read in MBRs that are bigger then DEV_BSIZE */
80219019Sgabor	unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE];
81219019Sgabor};
82219019Sgaborstruct mboot mboot;
83219019Sgabor
84219019Sgabor#define ACTIVE 0x80
85219019Sgabor#define BOOT_MAGIC 0xAA55
86219019Sgabor
87219019Sgaborint dos_cyls;
88219019Sgaborint dos_heads;
89219019Sgaborint dos_sectors;
90260264Sdimint dos_cylsecs;
91219019Sgabor
92219019Sgabor#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
93219019Sgabor#define DOSCYL(c)	(c & 0xff)
94219019Sgaborstatic int partition = -1;
95219019Sgabor
96219019Sgabor
97219019Sgabor#define MAX_ARGS	10
98219019Sgabor
99219019Sgaborstatic int	current_line_number;
100219019Sgabor
101219019Sgaborstatic int	geom_processed = 0;
102219019Sgaborstatic int	part_processed = 0;
103219019Sgaborstatic int	active_processed = 0;
104219019Sgabor
105219019Sgabor
106219019Sgabortypedef struct cmd {
107219019Sgabor    char		cmd;
108260264Sdim    int			n_args;
109219019Sgabor    struct arg {
110219019Sgabor	char	argtype;
111219019Sgabor	int	arg_val;
112219019Sgabor    }			args[MAX_ARGS];
113219019Sgabor} CMD;
114219019Sgabor
115219019Sgabor
116219019Sgaborstatic int a_flag  = 0;		/* set active partition */
117219019Sgaborstatic int i_flag  = 0;		/* replace partition data */
118219019Sgaborstatic int u_flag  = 0;		/* update partition data */
119219019Sgaborstatic int t_flag  = 0;		/* test only, if f_flag is given */
120219019Sgaborstatic char *f_flag = NULL;	/* Read config info from file */
121219019Sgaborstatic int v_flag  = 0;		/* Be verbose */
122219019Sgabor
123219019Sgaborstatic unsigned char bootcode[] = {
124219019Sgabor0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
125219019Sgabor0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
126219019Sgabor0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
127219019Sgabor0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
128219019Sgabor0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
129219019Sgabor0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
130219019Sgabor0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
131219019Sgabor0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
132219019Sgabor0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
133219019Sgabor'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
134219019Sgabor	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
135219019Sgabor'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
136219019Sgabor	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
137219019Sgabor'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
138219019Sgabor	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
139219019Sgabor'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
140219019Sgabor	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
141219019Sgabor
142219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
143219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
144219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
145219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
146219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
147219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
148219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
149219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
150219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
151219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
152219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
153219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
154219019Sgabor  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
155219019Sgabor};
156219019Sgabor
157219019Sgaborstruct part_type
158219019Sgabor{
159219019Sgabor unsigned char type;
160219019Sgabor char *name;
161219019Sgabor}part_types[] =
162219019Sgabor{
163219019Sgabor	 {0x00, "unused"}
164219019Sgabor	,{0x01, "Primary DOS with 12 bit FAT"}
165219019Sgabor	,{0x02, "XENIX / filesystem"}
166219019Sgabor	,{0x03, "XENIX /usr filesystem"}
167219019Sgabor	,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"}
168219019Sgabor	,{0x05, "Extended DOS"}
169219019Sgabor	,{0x06, "Primary 'big' DOS (> 32MB)"}
170219019Sgabor	,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"}
171219019Sgabor	,{0x08, "AIX filesystem"}
172219019Sgabor	,{0x09, "AIX boot partition or Coherent"}
173219019Sgabor	,{0x0A, "OS/2 Boot Manager or OPUS"}
174219019Sgabor	,{0x0B, "DOS or Windows 95 with 32 bit FAT"}
175219019Sgabor	,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"}
176219019Sgabor	,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"}
177219019Sgabor	,{0x0F, "Extended DOS, LBA"}
178219019Sgabor	,{0x10, "OPUS"}
179219019Sgabor	,{0x40, "VENIX 286"}
180219019Sgabor	,{0x50, "DM"}
181219019Sgabor	,{0x51, "DM"}
182219019Sgabor	,{0x52, "CP/M or Microport SysV/AT"}
183219019Sgabor	,{0x56, "GB"}
184219019Sgabor	,{0x61, "Speed"}
185219019Sgabor	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
186219019Sgabor	,{0x64, "Novell Netware 2.xx"}
187219019Sgabor	,{0x65, "Novell Netware 3.xx"}
188219019Sgabor	,{0x75, "PCIX"}
189219019Sgabor	,{0x80, "Minix 1.1 ... 1.4a"}
190219019Sgabor	,{0x81, "Minix 1.4b ... 1.5.10"}
191219019Sgabor	,{0x82, "Linux swap"}
192219019Sgabor	,{0x83, "Linux filesystem"}
193219019Sgabor	,{0x93, "Amoeba filesystem"}
194219019Sgabor	,{0x94, "Amoeba bad block table"}
195219019Sgabor	,{0xA5, "FreeBSD/NetBSD/386BSD"}
196219019Sgabor	,{0xA6, "OpenBSD"}
197219019Sgabor	,{0xA7, "NEXTSTEP"}
198219019Sgabor	,{0xB7, "BSDI BSD/386 filesystem"}
199219019Sgabor	,{0xB8, "BSDI BSD/386 swap"}
200219019Sgabor	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
201219019Sgabor	,{0xE1, "Speed"}
202219019Sgabor	,{0xE3, "Speed"}
203219019Sgabor	,{0xE4, "Speed"}
204219019Sgabor	,{0xF1, "Speed"}
205219019Sgabor	,{0xF2, "DOS 3.3+ Secondary"}
206219019Sgabor	,{0xF4, "Speed"}
207219019Sgabor	,{0xFF, "BBT (Bad Blocks Table)"}
208219019Sgabor};
209219019Sgabor
210219019Sgaborstatic void print_s0(int which);
211219019Sgaborstatic void print_part(int i);
212219019Sgaborstatic void init_sector0(unsigned long start);
213219019Sgaborstatic void init_boot(void);
214219019Sgaborstatic void change_part(int i);
215219019Sgaborstatic void print_params();
216219019Sgaborstatic void change_active(int which);
217219019Sgaborstatic void get_params_to_use();
218219019Sgaborstatic void dos(int sec, int size, unsigned char *c, unsigned char *s,
219219019Sgabor		unsigned char *h);
220219019Sgaborstatic int open_disk(int u_flag);
221219019Sgaborstatic ssize_t read_disk(off_t sector, void *buf);
222219019Sgaborstatic ssize_t write_disk(off_t sector, void *buf);
223219019Sgaborstatic int get_params();
224219019Sgaborstatic int read_s0();
225219019Sgaborstatic int write_s0();
226219019Sgaborstatic int ok(char *str);
227219019Sgaborstatic int decimal(char *str, int *num, int deflt);
228219019Sgaborstatic char *get_type(int type);
229219019Sgaborstatic int read_config(char *config_file);
230219019Sgaborstatic void reset_boot(void);
231219019Sgabor#if 0
232219019Sgaborstatic int hex(char *str, int *num, int deflt);
233219019Sgaborstatic int string(char *str, char **ans);
234219019Sgabor#endif
235219019Sgabor
236219019Sgabor
237219019Sgaborint
238219019Sgabormain(int argc, char *argv[])
239219019Sgabor{
240219019Sgabor	int	i;
241219019Sgabor
242219019Sgabor	name = *argv;
243219019Sgabor	{register char *cp = name;
244219019Sgabor		while (*cp) if (*cp++ == '/') name = cp;
245219019Sgabor	}
246219019Sgabor
247219019Sgabor	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
248219019Sgabor		if (*token++ != '-' || !*token)
249219019Sgabor			break;
250219019Sgabor		else { register int flag;
251219019Sgabor			for ( ; (flag = *token++) ; ) {
252219019Sgabor				switch (flag) {
253219019Sgabor				case '1':
254219019Sgabor					partition = 1;
255219019Sgabor					break;
256219019Sgabor				case '2':
257219019Sgabor					partition = 2;
258219019Sgabor					break;
259219019Sgabor				case '3':
260219019Sgabor					partition = 3;
261219019Sgabor					break;
262219019Sgabor				case '4':
263219019Sgabor					partition = 4;
264219019Sgabor					break;
265219019Sgabor				case 'a':
266219019Sgabor					a_flag = 1;
267219019Sgabor					break;
268219019Sgabor				case 'f':
269219019Sgabor					if (*token)
270219019Sgabor					{
271219019Sgabor					    f_flag = token;
272219019Sgabor					    token = "";
273219019Sgabor					}
274219019Sgabor					else
275219019Sgabor					{
276219019Sgabor					    if (argc == 1)
277219019Sgabor					    {
278219019Sgabor						goto usage;
279219019Sgabor					    }
280219019Sgabor					    --argc;
281219019Sgabor					    f_flag = *++argv;
282219019Sgabor					}
283219019Sgabor					/*
284219019Sgabor					 * u_flag is needed, because we're
285219019Sgabor					 * writing to the disk.
286219019Sgabor					 */
287219019Sgabor					u_flag = 1;
288219019Sgabor					break;
289219019Sgabor				case 'i':
290219019Sgabor					i_flag = 1;
291219019Sgabor				case 'u':
292219019Sgabor					u_flag = 1;
293219019Sgabor					break;
294219019Sgabor				case 't':
295219019Sgabor					t_flag = 1;
296219019Sgabor				case 'v':
297219019Sgabor					v_flag = 1;
298219019Sgabor					break;
299219019Sgabor				default:
300219019Sgabor					goto usage;
301219019Sgabor				}
302219019Sgabor			}
303219019Sgabor		}
304219019Sgabor	}
305219019Sgabor
306219019Sgabor	if (argc > 0)
307219019Sgabor	{
308219019Sgabor		static char realname[12];
309219019Sgabor
310219019Sgabor		if(strncmp(argv[0], "/dev", 4) == 0)
311219019Sgabor			disk = argv[0];
312219019Sgabor		else
313219019Sgabor		{
314219019Sgabor			snprintf(realname, 12, "/dev/r%s", argv[0]);
315219019Sgabor			disk = realname;
316219019Sgabor		}
317219019Sgabor
318219019Sgabor		if (open_disk(u_flag) < 0)
319219019Sgabor		{
320219019Sgabor			fprintf(stderr, "Cannot open disk %s (%s)\n",
321219019Sgabor				disk, sys_errlist[errno]);
322219019Sgabor			exit(1);
323219019Sgabor		}
324219019Sgabor	}
325219019Sgabor	else
326219019Sgabor	{
327219019Sgabor		int i, rv = 0;
328219019Sgabor
329219019Sgabor		for(i = 0; disks[i]; i++)
330219019Sgabor		{
331219019Sgabor			disk = disks[i];
332219019Sgabor			rv = open_disk(u_flag);
333219019Sgabor			if(rv != -2) break;
334219019Sgabor		}
335219019Sgabor		if(rv < 0)
336219019Sgabor		{
337219019Sgabor			fprintf(stderr, "Cannot open any disk (%s)\n",
338219019Sgabor				sys_errlist[errno]);
339219019Sgabor			exit(1);
340219019Sgabor		}
341219019Sgabor	}
342219019Sgabor
343219019Sgabor	printf("******* Working on device %s *******\n",disk);
344219019Sgabor
345219019Sgabor	if (f_flag)
346219019Sgabor	{
347219019Sgabor	    if (read_s0() || i_flag)
348219019Sgabor	    {
349219019Sgabor		reset_boot();
350219019Sgabor	    }
351219019Sgabor
352219019Sgabor	    if (!read_config(f_flag))
353219019Sgabor	    {
354219019Sgabor		exit(1);
355219019Sgabor	    }
356219019Sgabor	    if (v_flag)
357219019Sgabor	    {
358219019Sgabor		print_s0(-1);
359219019Sgabor	    }
360219019Sgabor	    if (!t_flag)
361219019Sgabor	    {
362219019Sgabor		write_s0();
363219019Sgabor	    }
364219019Sgabor	}
365219019Sgabor	else
366219019Sgabor	{
367219019Sgabor	    if(u_flag)
368219019Sgabor	    {
369219019Sgabor		get_params_to_use();
370219019Sgabor	    }
371219019Sgabor	    else
372219019Sgabor	    {
373219019Sgabor		print_params();
374219019Sgabor	    }
375219019Sgabor
376219019Sgabor	    if (read_s0())
377219019Sgabor		init_sector0(1);
378219019Sgabor
379219019Sgabor	    printf("Media sector size is %d\n", secsize);
380219019Sgabor	    printf("Warning: BIOS sector numbering starts with sector 1\n");
381219019Sgabor	    printf("Information from DOS bootblock is:\n");
382219019Sgabor	    if (partition == -1)
383219019Sgabor		for (i = 1; i <= NDOSPART; i++)
384219019Sgabor		    change_part(i);
385219019Sgabor	    else
386219019Sgabor		change_part(partition);
387219019Sgabor
388219019Sgabor	    if (u_flag || a_flag)
389219019Sgabor		change_active(partition);
390219019Sgabor
391219019Sgabor	    if (u_flag || a_flag) {
392219019Sgabor		if (!t_flag)
393219019Sgabor		{
394219019Sgabor		    printf("\nWe haven't changed the partition table yet.  ");
395219019Sgabor		    printf("This is your last chance.\n");
396219019Sgabor		}
397219019Sgabor		print_s0(-1);
398219019Sgabor		if (!t_flag)
399219019Sgabor		{
400219019Sgabor		    if (ok("Should we write new partition table?"))
401219019Sgabor			write_s0();
402219019Sgabor		}
403219019Sgabor		else
404219019Sgabor		{
405219019Sgabor		    printf("\n-t flag specified -- partition table not written.\n");
406219019Sgabor		}
407219019Sgabor	    }
408219019Sgabor	}
409219019Sgabor
410219019Sgabor	exit(0);
411219019Sgabor
412219019Sgaborusage:
413219019Sgabor	printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{1,2,3,4}] [disk]\n");
414219019Sgabor	return(1);
415219019Sgabor}
416219019Sgabor
417219019Sgaborstatic void
418219019Sgaborprint_s0(int which)
419219019Sgabor{
420219019Sgaborint	i;
421219019Sgabor
422219019Sgabor	print_params();
423219019Sgabor	printf("Information from DOS bootblock is:\n");
424219019Sgabor	if (which == -1)
425219019Sgabor		for (i = 1; i <= NDOSPART; i++)
426219019Sgabor			printf("%d: ", i), print_part(i);
427219019Sgabor	else
428219019Sgabor		print_part(which);
429219019Sgabor}
430219019Sgabor
431219019Sgaborstatic struct dos_partition mtpart = { 0 };
432219019Sgabor
433219019Sgaborstatic void
434219019Sgaborprint_part(int i)
435219019Sgabor{
436219019Sgabor	struct	  dos_partition *partp;
437219019Sgabor	u_int64_t part_mb;
438219019Sgabor
439219019Sgabor	partp = ((struct dos_partition *) &mboot.parts) + i - 1;
440219019Sgabor
441219019Sgabor	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
442219019Sgabor		printf("<UNUSED>\n");
443219019Sgabor		return;
444219019Sgabor	}
445219019Sgabor	/*
446219019Sgabor	 * Be careful not to overflow.
447219019Sgabor	 */
448219019Sgabor	part_mb = partp->dp_size;
449219019Sgabor	part_mb *= secsize;
450219019Sgabor	part_mb /= (1024 * 1024);
451219019Sgabor	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
452219019Sgabor	printf("    start %ld, size %ld (%qd Meg), flag %x%s\n",
453219019Sgabor		partp->dp_start,
454219019Sgabor		partp->dp_size,
455219019Sgabor		part_mb,
456219019Sgabor		partp->dp_flag,
457219019Sgabor		partp->dp_flag == ACTIVE ? " (active)" : "");
458219019Sgabor	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
459219019Sgabor		,DPCYL(partp->dp_scyl, partp->dp_ssect)
460219019Sgabor		,DPSECT(partp->dp_ssect)
461219019Sgabor		,partp->dp_shd
462219019Sgabor		,DPCYL(partp->dp_ecyl, partp->dp_esect)
463219019Sgabor		,DPSECT(partp->dp_esect)
464219019Sgabor		,partp->dp_ehd);
465219019Sgabor}
466219019Sgabor
467219019Sgabor
468219019Sgaborstatic void
469219019Sgaborinit_boot(void)
470219019Sgabor{
471219019Sgabor	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
472219019Sgabor	mboot.signature = BOOT_MAGIC;
473219019Sgabor}
474219019Sgabor
475219019Sgabor
476219019Sgaborstatic void
477219019Sgaborinit_sector0(unsigned long start)
478219019Sgabor{
479219019Sgaborstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
480219019Sgaborunsigned long size = disksecs - start;
481219019Sgabor
482219019Sgabor	init_boot();
483219019Sgabor
484219019Sgabor	partp->dp_typ = DOSPTYP_386BSD;
485219019Sgabor	partp->dp_flag = ACTIVE;
486219019Sgabor	partp->dp_start = start;
487219019Sgabor	partp->dp_size = size;
488219019Sgabor
489219019Sgabor	dos(partp->dp_start, partp->dp_size,
490219019Sgabor	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
491219019Sgabor	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
492219019Sgabor	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
493219019Sgabor}
494219019Sgabor
495219019Sgaborstatic void
496219019Sgaborchange_part(int i)
497219019Sgabor{
498219019Sgaborstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1;
499219019Sgabor
500219019Sgabor    printf("The data for partition %d is:\n", i);
501219019Sgabor    print_part(i);
502
503    if (u_flag && ok("Do you want to change it?")) {
504	int tmp;
505
506	if (i_flag) {
507		bzero((char *)partp, sizeof (struct dos_partition));
508		if (i == 4) {
509			init_sector0(1);
510			printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n");
511			print_part(i);
512		}
513	}
514
515	do {
516		Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp);
517		Decimal("start", partp->dp_start, tmp);
518		Decimal("size", partp->dp_size, tmp);
519
520		if (ok("Explicitly specify beg/end address ?"))
521		{
522			int	tsec,tcyl,thd;
523			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
524			thd = partp->dp_shd;
525			tsec = DPSECT(partp->dp_ssect);
526			Decimal("beginning cylinder", tcyl, tmp);
527			Decimal("beginning head", thd, tmp);
528			Decimal("beginning sector", tsec, tmp);
529			partp->dp_scyl = DOSCYL(tcyl);
530			partp->dp_ssect = DOSSECT(tsec,tcyl);
531			partp->dp_shd = thd;
532
533			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
534			thd = partp->dp_ehd;
535			tsec = DPSECT(partp->dp_esect);
536			Decimal("ending cylinder", tcyl, tmp);
537			Decimal("ending head", thd, tmp);
538			Decimal("ending sector", tsec, tmp);
539			partp->dp_ecyl = DOSCYL(tcyl);
540			partp->dp_esect = DOSSECT(tsec,tcyl);
541			partp->dp_ehd = thd;
542		} else {
543			dos(partp->dp_start, partp->dp_size,
544			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
545			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
546			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
547		}
548
549		print_part(i);
550	} while (!ok("Are we happy with this entry?"));
551    }
552}
553
554static void
555print_params()
556{
557	printf("parameters extracted from in-core disklabel are:\n");
558	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
559			,cyls,heads,sectors,cylsecs);
560	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
561		printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
562	printf("parameters to be used for BIOS calculations are:\n");
563	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
564		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
565}
566
567static void
568change_active(int which)
569{
570int i;
571int active = 4, tmp;
572struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
573
574	if (a_flag && which != -1)
575		active = which;
576	if (!ok("Do you want to change the active partition?"))
577		return;
578setactive:
579	active = 4;
580	do {
581		Decimal("active partition", active, tmp);
582		if (active < 1 || 4 < active) {
583			printf("Active partition number must be in range 1-4."
584					"  Try again.\n");
585			goto setactive;
586		}
587	} while (!ok("Are you happy with this choice"));
588	for (i = 0; i < NDOSPART; i++)
589		partp[i].dp_flag = 0;
590	if (active > 0 && active <= NDOSPART)
591		partp[active-1].dp_flag = ACTIVE;
592}
593
594void
595get_params_to_use()
596{
597	int	tmp;
598	print_params();
599	if (ok("Do you want to change our idea of what BIOS thinks ?"))
600	{
601		do
602		{
603			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
604			Decimal("BIOS's idea of #heads", dos_heads, tmp);
605			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
606			dos_cylsecs = dos_heads * dos_sectors;
607			print_params();
608		}
609		while(!ok("Are you happy with this choice"));
610	}
611}
612
613
614/***********************************************\
615* Change real numbers into strange dos numbers	*
616\***********************************************/
617static void
618dos(sec, size, c, s, h)
619int sec, size;
620unsigned char *c, *s, *h;
621{
622int cy;
623int hd;
624
625	if (sec == 0 && size == 0) {
626		*s = *c = *h = 0;
627		return;
628	}
629
630	cy = sec / ( dos_cylsecs );
631	sec = sec - cy * ( dos_cylsecs );
632
633	hd = sec / dos_sectors;
634	sec = (sec - hd * dos_sectors) + 1;
635
636	*h = hd;
637	*c = cy & 0xff;
638	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
639}
640
641int fd;
642
643	/* Getting device status */
644
645static int
646open_disk(int u_flag)
647{
648struct stat 	st;
649
650	if (stat(disk, &st) == -1) {
651		fprintf(stderr, "%s: Can't get file status of %s\n",
652			name, disk);
653		return -1;
654	}
655	if ( !(st.st_mode & S_IFCHR) )
656		fprintf(stderr,"%s: Device %s is not character special\n",
657			name, disk);
658	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
659		if(errno == ENXIO)
660			return -2;
661		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
662		return -1;
663	}
664	if (get_params(0) == -1) {
665		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
666			name, disk);
667		return -1;
668	}
669	return fd;
670}
671
672static ssize_t
673read_disk(off_t sector, void *buf)
674{
675	lseek(fd,(sector * 512), 0);
676	if( secsize == 0 )
677		for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
678			{
679			/* try the read */
680			int size = read(fd, buf, secsize);
681			if( size == secsize )
682				/* it worked so return */
683				return secsize;
684			}
685	else
686		return read( fd, buf, secsize );
687
688	/* we failed to read at any of the sizes */
689	return -1;
690}
691
692static ssize_t
693write_disk(off_t sector, void *buf)
694{
695	lseek(fd,(sector * 512), 0);
696	/* write out in the size that the read_disk found worked */
697	return write(fd, buf, secsize);
698}
699
700static int
701get_params()
702{
703
704    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
705	fprintf(stderr,
706		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
707		name, disk);
708	dos_cyls = cyls = 1;
709	dos_heads = heads = 1;
710	dos_sectors = sectors = 1;
711	dos_cylsecs = cylsecs = heads * sectors;
712	disksecs = cyls * heads * sectors;
713	return disksecs;
714    }
715
716    dos_cyls = cyls = disklabel.d_ncylinders;
717    dos_heads = heads = disklabel.d_ntracks;
718    dos_sectors = sectors = disklabel.d_nsectors;
719    dos_cylsecs = cylsecs = heads * sectors;
720    disksecs = cyls * heads * sectors;
721
722    return (disksecs);
723}
724
725
726static int
727read_s0()
728{
729	if (read_disk(0, (char *) mboot.bootinst) == -1) {
730		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
731		return -1;
732	}
733	if (mboot.signature != BOOT_MAGIC) {
734		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
735			name);
736		/* So should we initialize things */
737		return -1;
738	}
739	return 0;
740}
741
742static int
743write_s0()
744{
745	int	flag;
746	if (iotest) {
747		print_s0(-1);
748		return 0;
749	}
750	/*
751	 * write enable label sector before write (if necessary),
752	 * disable after writing.
753	 * needed if the disklabel protected area also protects
754	 * sector 0. (e.g. empty disk)
755	 */
756	flag = 1;
757#ifdef NOT_NOW
758	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
759		perror("ioctl DIOCWLABEL");
760#endif
761	if (write_disk(0, (char *) mboot.bootinst) == -1) {
762		fprintf(stderr, "%s: Can't write fdisk partition table\n",
763			name);
764		return -1;
765	flag = 0;
766#ifdef NOT_NOW
767	(void) ioctl(fd, DIOCWLABEL, &flag);
768#endif
769	}
770	return(0);
771}
772
773
774static int
775ok(str)
776char *str;
777{
778	printf("%s [n] ", str);
779	fgets(lbuf, LBUF, stdin);
780	lbuf[strlen(lbuf)-1] = 0;
781
782	if (*lbuf &&
783		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
784		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
785		return 1;
786	else
787		return 0;
788}
789
790static int
791decimal(char *str, int *num, int deflt)
792{
793int acc = 0, c;
794char *cp;
795
796	while (1) {
797		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
798		fgets(lbuf, LBUF, stdin);
799		lbuf[strlen(lbuf)-1] = 0;
800
801		if (!*lbuf)
802			return 0;
803
804		cp = lbuf;
805		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
806		if (!c)
807			return 0;
808		while ((c = *cp++)) {
809			if (c <= '9' && c >= '0')
810				acc = acc * 10 + c - '0';
811			else
812				break;
813		}
814		if (c == ' ' || c == '\t')
815			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
816		if (!c) {
817			*num = acc;
818			return 1;
819		} else
820			printf("%s is an invalid decimal number.  Try again.\n",
821				lbuf);
822	}
823
824}
825
826#if 0
827static int
828hex(char *str, int *num, int deflt)
829{
830int acc = 0, c;
831char *cp;
832
833	while (1) {
834		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
835		fgets(lbuf, LBUF, stdin);
836		lbuf[strlen(lbuf)-1] = 0;
837
838		if (!*lbuf)
839			return 0;
840
841		cp = lbuf;
842		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
843		if (!c)
844			return 0;
845		while ((c = *cp++)) {
846			if (c <= '9' && c >= '0')
847				acc = (acc << 4) + c - '0';
848			else if (c <= 'f' && c >= 'a')
849				acc = (acc << 4) + c - 'a' + 10;
850			else if (c <= 'F' && c >= 'A')
851				acc = (acc << 4) + c - 'A' + 10;
852			else
853				break;
854		}
855		if (c == ' ' || c == '\t')
856			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
857		if (!c) {
858			*num = acc;
859			return 1;
860		} else
861			printf("%s is an invalid hex number.  Try again.\n",
862				lbuf);
863	}
864
865}
866
867static int
868string(char *str, char **ans)
869{
870int c;
871char *cp = lbuf;
872
873	while (1) {
874		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
875		fgets(lbuf, LBUF, stdin);
876		lbuf[strlen(lbuf)-1] = 0;
877
878		if (!*lbuf)
879			return 0;
880
881		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
882		if (c == '"') {
883			c = *++cp;
884			*ans = cp;
885			while ((c = *cp) && c != '"') cp++;
886		} else {
887			*ans = cp;
888			while ((c = *cp) && c != ' ' && c != '\t') cp++;
889		}
890
891		if (c)
892			*cp = 0;
893		return 1;
894	}
895}
896#endif
897
898static char *
899get_type(int type)
900{
901	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
902	int	counter = 0;
903	struct	part_type *ptr = part_types;
904
905
906	while(counter < numentries)
907	{
908		if(ptr->type == type)
909		{
910			return(ptr->name);
911		}
912		ptr++;
913		counter++;
914	}
915	return("unknown");
916}
917
918
919static void
920parse_config_line(line, command)
921    char	*line;
922    CMD		*command;
923{
924    char	*cp, *end;
925
926    cp = line;
927    while (1)	/* dirty trick used to insure one exit point for this
928		   function */
929    {
930	memset(command, 0, sizeof(*command));
931
932	while (isspace(*cp)) ++cp;
933	if (*cp == '\0' || *cp == '#')
934	{
935	    break;
936	}
937	command->cmd = *cp++;
938
939	/*
940	 * Parse args
941	 */
942	while (1)
943	{
944	    while (isspace(*cp)) ++cp;
945	    if (*cp == '#')
946	    {
947		break;		/* found comment */
948	    }
949	    if (isalpha(*cp))
950	    {
951		command->args[command->n_args].argtype = *cp++;
952	    }
953	    if (!isdigit(*cp))
954	    {
955		break;		/* assume end of line */
956	    }
957	    end = NULL;
958	    command->args[command->n_args].arg_val = strtol(cp, &end, 0);
959	    if (cp == end)
960	    {
961		break;		/* couldn't parse number */
962	    }
963	    cp = end;
964	    command->n_args++;
965	}
966	break;
967    }
968}
969
970
971static int
972process_geometry(command)
973    CMD		*command;
974{
975    int		status = 1, i;
976
977    while (1)
978    {
979	geom_processed = 1;
980	if (part_processed)
981	{
982	    fprintf(stderr,
983		    "%s: ERROR line %d: the geometry specification line must occur before\n\
984    all partition specifications.\n",
985		    name, current_line_number);
986	    status = 0;
987	    break;
988	}
989	if (command->n_args != 3)
990	{
991	    fprintf(stderr,
992		    "%s: ERROR line %d: incorrect number of geometry args\n",
993		    name, current_line_number);
994	    status = 0;
995	    break;
996	}
997	dos_cyls = -1;
998	dos_heads = -1;
999	dos_sectors = -1;
1000	for (i = 0; i < 3; ++i)
1001	{
1002	    switch (command->args[i].argtype)
1003	    {
1004	    case 'c':
1005		dos_cyls = command->args[i].arg_val;
1006		break;
1007	    case 'h':
1008		dos_heads = command->args[i].arg_val;
1009		break;
1010	    case 's':
1011		dos_sectors = command->args[i].arg_val;
1012		break;
1013	    default:
1014		fprintf(stderr,
1015			"%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n",
1016			name, current_line_number, command->args[i].argtype,
1017			command->args[i].argtype);
1018		status = 0;
1019		break;
1020	    }
1021	}
1022	if (status == 0)
1023	{
1024	    break;
1025	}
1026
1027	dos_cylsecs = dos_heads * dos_sectors;
1028
1029	/*
1030	 * Do sanity checks on parameter values
1031	 */
1032	if (dos_cyls < 0)
1033	{
1034	    fprintf(stderr,
1035		    "%s: ERROR line %d: number of cylinders not specified\n",
1036		    name, current_line_number);
1037	    status = 0;
1038	}
1039	if (dos_cyls == 0 || dos_cyls > 1024)
1040	{
1041	    fprintf(stderr,
1042		    "%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\
1043    (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
1044    is dedicated to FreeBSD).\n",
1045		    name, current_line_number, dos_cyls);
1046	}
1047
1048	if (dos_heads < 0)
1049	{
1050	    fprintf(stderr,
1051		    "%s: ERROR line %d: number of heads not specified\n",
1052		    name, current_line_number);
1053	    status = 0;
1054	}
1055	else if (dos_heads < 1 || dos_heads > 256)
1056	{
1057	    fprintf(stderr,
1058		    "%s: ERROR line %d: number of heads must be within (1-256)\n",
1059		    name, current_line_number);
1060	    status = 0;
1061	}
1062
1063	if (dos_sectors < 0)
1064	{
1065	    fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n",
1066		    name, current_line_number);
1067	    status = 0;
1068	}
1069	else if (dos_sectors < 1 || dos_sectors > 63)
1070	{
1071	    fprintf(stderr,
1072		    "%s: ERROR line %d: number of sectors must be within (1-63)\n",
1073		    name, current_line_number);
1074	    status = 0;
1075	}
1076
1077	break;
1078    }
1079    return (status);
1080}
1081
1082
1083static int
1084process_partition(command)
1085    CMD		*command;
1086{
1087    int				status = 0, partition;
1088    unsigned long		chunks, adj_size, max_end;
1089    struct dos_partition	*partp;
1090
1091    while (1)
1092    {
1093	part_processed = 1;
1094	if (command->n_args != 4)
1095	{
1096	    fprintf(stderr,
1097		    "%s: ERROR line %d: incorrect number of partition args\n",
1098		    name, current_line_number);
1099	    break;
1100	}
1101	partition = command->args[0].arg_val;
1102	if (partition < 1 || partition > 4)
1103	{
1104	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
1105		    name, current_line_number, partition);
1106	    break;
1107	}
1108	partp = ((struct dos_partition *) &mboot.parts) + partition - 1;
1109	bzero((char *)partp, sizeof (struct dos_partition));
1110	partp->dp_typ = command->args[1].arg_val;
1111	partp->dp_start = command->args[2].arg_val;
1112	partp->dp_size = command->args[3].arg_val;
1113	max_end = partp->dp_start + partp->dp_size;
1114
1115	if (partp->dp_typ == 0)
1116	{
1117	    /*
1118	     * Get out, the partition is marked as unused.
1119	     */
1120	    /*
1121	     * Insure that it's unused.
1122	     */
1123	    bzero((char *)partp, sizeof (struct dos_partition));
1124	    status = 1;
1125	    break;
1126	}
1127
1128	/*
1129	 * Adjust start upwards, if necessary, to fall on an head boundary.
1130	 */
1131	if (partp->dp_start % dos_sectors != 0)
1132	{
1133	    adj_size =
1134		(partp->dp_start / dos_sectors + 1) * dos_sectors;
1135	    if (adj_size > max_end)
1136	    {
1137		/*
1138		 * Can't go past end of partition
1139		 */
1140		fprintf(stderr,
1141			"%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\
1142    a cylinder boundary.\n",
1143			name, current_line_number, partition);
1144		break;
1145	    }
1146	    fprintf(stderr,
1147		    "%s: WARNING: adjusting start offset of partition '%d' from %d\n\
1148    to %d, to round to an head boundary.\n",
1149		    name, partition, partp->dp_start, adj_size);
1150	    partp->dp_start = adj_size;
1151	}
1152
1153	/*
1154	 * Adjust size downwards, if necessary, to fall on a cylinder
1155	 * boundary.
1156	 */
1157	chunks =
1158	    ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
1159	adj_size = chunks - partp->dp_start;
1160	if (adj_size != partp->dp_size)
1161	{
1162	    fprintf(stderr,
1163		    "%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\
1164    to round to a cylinder boundary.\n",
1165		    name, partition, partp->dp_size, adj_size);
1166	    if (chunks > 0)
1167	    {
1168		partp->dp_size = adj_size;
1169	    }
1170	    else
1171	    {
1172		partp->dp_size = 0;
1173	    }
1174	}
1175	if (partp->dp_size < 1)
1176	{
1177	    fprintf(stderr,
1178		    "%s: ERROR line %d: size for partition '%d' is zero.\n",
1179		    name, current_line_number, partition);
1180	    break;
1181	}
1182
1183	dos(partp->dp_start, partp->dp_size,
1184	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
1185	dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
1186	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
1187	status = 1;
1188	break;
1189    }
1190    return (status);
1191}
1192
1193
1194static int
1195process_active(command)
1196    CMD		*command;
1197{
1198    int				status = 0, partition, i;
1199    struct dos_partition	*partp;
1200
1201    while (1)
1202    {
1203	active_processed = 1;
1204	if (command->n_args != 1)
1205	{
1206	    fprintf(stderr,
1207		    "%s: ERROR line %d: incorrect number of active args\n",
1208		    name, current_line_number);
1209	    status = 0;
1210	    break;
1211	}
1212	partition = command->args[0].arg_val;
1213	if (partition < 1 || partition > 4)
1214	{
1215	    fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
1216		    name, current_line_number, partition);
1217	    break;
1218	}
1219	/*
1220	 * Reset active partition
1221	 */
1222	partp = ((struct dos_partition *) &mboot.parts);
1223	for (i = 0; i < NDOSPART; i++)
1224	    partp[i].dp_flag = 0;
1225	partp[partition-1].dp_flag = ACTIVE;
1226
1227	status = 1;
1228	break;
1229    }
1230    return (status);
1231}
1232
1233
1234static int
1235process_line(line)
1236    char	*line;
1237{
1238    CMD		command;
1239    int		status = 1;
1240
1241    while (1)
1242    {
1243	parse_config_line(line, &command);
1244	switch (command.cmd)
1245	{
1246	case 0:
1247	    /*
1248	     * Comment or blank line
1249	     */
1250	    break;
1251	case 'g':
1252	    /*
1253	     * Set geometry
1254	     */
1255	    status = process_geometry(&command);
1256	    break;
1257	case 'p':
1258	    status = process_partition(&command);
1259	    break;
1260	case 'a':
1261	    status = process_active(&command);
1262	    break;
1263	default:
1264	    status = 0;
1265	    break;
1266	}
1267	break;
1268    }
1269    return (status);
1270}
1271
1272
1273static int
1274read_config(config_file)
1275    char *config_file;
1276{
1277    FILE	*fp = NULL;
1278    int		status = 1;
1279    char	buf[1010];
1280
1281    while (1)	/* dirty trick used to insure one exit point for this
1282		   function */
1283    {
1284	if (strcmp(config_file, "-") != 0)
1285	{
1286	    /*
1287	     * We're not reading from stdin
1288	     */
1289	    if ((fp = fopen(config_file, "r")) == NULL)
1290	    {
1291		status = 0;
1292		break;
1293	    }
1294	}
1295	else
1296	{
1297	    fp = stdin;
1298	}
1299	current_line_number = 0;
1300	while (!feof(fp))
1301	{
1302	    if (fgets(buf, sizeof(buf), fp) == NULL)
1303	    {
1304		break;
1305	    }
1306	    ++current_line_number;
1307	    status = process_line(buf);
1308	    if (status == 0)
1309	    {
1310		break;
1311	    }
1312	}
1313	break;
1314    }
1315    if (fp)
1316    {
1317	/*
1318	 * It doesn't matter if we're reading from stdin, as we've reached EOF
1319	 */
1320	fclose(fp);
1321    }
1322    return (status);
1323}
1324
1325
1326static void
1327reset_boot(void)
1328{
1329    int				i;
1330    struct dos_partition	*partp;
1331
1332    init_boot();
1333    for (i = 0; i < 4; ++i)
1334    {
1335	partp = ((struct dos_partition *) &mboot.parts) + i;
1336	bzero((char *)partp, sizeof (struct dos_partition));
1337    }
1338}
1339