Home | History | Annotate | Line # | Download | only in disklabel
interact.c revision 1.17
      1  1.17     lukem /*	$NetBSD: interact.c,v 1.17 2000/12/24 07:08:03 lukem Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
      5   1.1  christos  *
      6   1.1  christos  * Redistribution and use in source and binary forms, with or without
      7   1.1  christos  * modification, are permitted provided that the following conditions
      8   1.1  christos  * are met:
      9   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     10   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     11   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     13   1.1  christos  *    documentation and/or other materials provided with the distribution.
     14   1.1  christos  * 3. All advertising materials mentioning features or use of this software
     15   1.1  christos  *    must display the following acknowledgement:
     16   1.1  christos  *	This product includes software developed by Christos Zoulas.
     17   1.1  christos  * 4. The name of the author may not be used to endorse or promote products
     18   1.1  christos  *    derived from this software without specific prior written permission.
     19   1.1  christos  *
     20   1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21   1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22   1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23   1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24   1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25   1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26   1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27   1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28   1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29   1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30   1.1  christos  */
     31   1.1  christos 
     32   1.5  christos #include <sys/cdefs.h>
     33   1.1  christos #ifndef lint
     34  1.17     lukem __RCSID("$NetBSD: interact.c,v 1.17 2000/12/24 07:08:03 lukem Exp $");
     35   1.1  christos #endif /* lint */
     36   1.1  christos 
     37  1.11       mrg #include <sys/param.h>
     38  1.11       mrg #define FSTYPENAMES
     39  1.11       mrg #define DKTYPENAMES
     40  1.11       mrg #include <sys/disklabel.h>
     41  1.11       mrg 
     42  1.11       mrg #include <err.h>
     43   1.1  christos #include <stdio.h>
     44   1.1  christos #include <string.h>
     45   1.1  christos #include <stdlib.h>
     46   1.2  christos #include <util.h>
     47   1.1  christos 
     48   1.1  christos #include "extern.h"
     49   1.1  christos 
     50  1.16     lukem static void	cmd_help(struct disklabel *, char *, int);
     51  1.16     lukem static void	cmd_chain(struct disklabel *, char *, int);
     52  1.16     lukem static void	cmd_print(struct disklabel *, char *, int);
     53  1.16     lukem static void	cmd_printall(struct disklabel *, char *, int);
     54  1.16     lukem static void	cmd_info(struct disklabel *, char *, int);
     55  1.16     lukem static void	cmd_part(struct disklabel *, char *, int);
     56  1.16     lukem static void	cmd_label(struct disklabel *, char *, int);
     57  1.16     lukem static void	cmd_round(struct disklabel *, char *, int);
     58  1.16     lukem static void	cmd_name(struct disklabel *, char *, int);
     59  1.16     lukem static int	runcmd(struct disklabel *, char *, int);
     60  1.16     lukem static int	getinput(const char *, const char *, const char *, char *);
     61  1.16     lukem static int	alphacmp(const void *, const void *);
     62  1.16     lukem static void	defnum(struct disklabel *, char *, int);
     63  1.16     lukem static void	dumpnames(const char *, const char * const *, size_t);
     64  1.16     lukem static int	getnum(struct disklabel *, char *, int);
     65   1.1  christos 
     66   1.1  christos static int rounding = 0;	/* sector rounding */
     67   1.9  christos static int chaining = 0;	/* make partitions contiguous */
     68   1.1  christos 
     69   1.1  christos static struct cmds {
     70   1.1  christos 	const char *name;
     71  1.16     lukem 	void (*func)(struct disklabel *, char *, int);
     72   1.1  christos 	const char *help;
     73   1.1  christos } cmds[] = {
     74   1.1  christos 	{ "?",	cmd_help,	"print this menu" },
     75   1.9  christos 	{ "C",	cmd_chain,	"make partitions contiguous" },
     76  1.11       mrg 	{ "E",	cmd_printall,	"print disk label and current partition table"},
     77  1.11       mrg 	{ "I",	cmd_info,	"change label information" },
     78   1.2  christos 	{ "N",	cmd_name,	"name the label" },
     79   1.2  christos 	{ "P",	cmd_print,	"print current partition table" },
     80   1.2  christos 	{ "Q",	NULL,		"quit" },
     81   1.2  christos 	{ "R",	cmd_round,	"rounding (c)ylinders (s)ectors" },
     82   1.2  christos 	{ "W",	cmd_label,	"write the current partition table" },
     83   1.1  christos 	{ NULL, NULL,		NULL }
     84   1.1  christos };
     85   1.1  christos 
     86   1.1  christos 
     87   1.1  christos 
     88   1.1  christos static void
     89  1.16     lukem cmd_help(struct disklabel *lp, char *s, int fd)
     90   1.1  christos {
     91   1.1  christos 	struct cmds *cmd;
     92   1.2  christos 
     93   1.1  christos 	for (cmd = cmds; cmd->name != NULL; cmd++)
     94   1.1  christos 		printf("%s\t%s\n", cmd->name, cmd->help);
     95   1.2  christos 	printf("[a-%c]\tdefine named partition\n",
     96   1.2  christos 	    'a' + getmaxpartitions() - 1);
     97   1.1  christos }
     98   1.1  christos 
     99   1.1  christos 
    100   1.1  christos static void
    101  1.16     lukem cmd_chain(struct disklabel *lp, char *s, int fd)
    102   1.9  christos {
    103  1.16     lukem 	int	i;
    104  1.16     lukem 	char	line[BUFSIZ];
    105   1.9  christos 
    106   1.9  christos 	i = getinput(":", "Automatically adjust partitions",
    107   1.9  christos 	    chaining ? "yes" : "no", line);
    108   1.9  christos 	if (i <= 0)
    109   1.9  christos 		return;
    110   1.9  christos 
    111   1.9  christos 	switch (line[0]) {
    112   1.9  christos 	case 'y':
    113   1.9  christos 		chaining = 1;
    114   1.9  christos 		return;
    115   1.9  christos 	case 'n':
    116   1.9  christos 		chaining = 0;
    117   1.9  christos 		return;
    118   1.9  christos 	default:
    119   1.9  christos 		printf("Invalid answer\n");
    120   1.9  christos 		return;
    121   1.9  christos 	}
    122   1.9  christos }
    123   1.9  christos 
    124  1.16     lukem 
    125   1.9  christos static void
    126  1.16     lukem cmd_printall(struct disklabel *lp, char *s, int fd)
    127  1.11       mrg {
    128  1.11       mrg 
    129  1.17     lukem 	showinfo(stdout, lp, specname);
    130  1.17     lukem 	showpartitions(stdout, lp, Cflag);
    131  1.11       mrg }
    132  1.11       mrg 
    133  1.16     lukem 
    134  1.11       mrg static void
    135  1.16     lukem cmd_print(struct disklabel *lp, char *s, int fd)
    136   1.1  christos {
    137  1.16     lukem 
    138  1.17     lukem 	showpartitions(stdout, lp, Cflag);
    139   1.1  christos }
    140   1.1  christos 
    141  1.16     lukem 
    142  1.11       mrg static void
    143  1.16     lukem cmd_info(struct disklabel *lp, char *s, int fd)
    144  1.16     lukem {
    145  1.16     lukem 	char	line[BUFSIZ];
    146  1.16     lukem 	char	def[BUFSIZ];
    147  1.16     lukem 	int	v, i;
    148  1.11       mrg 	u_int32_t u;
    149  1.11       mrg 
    150  1.11       mrg 	printf("# Current values:\n");
    151  1.17     lukem 	showinfo(stdout, lp, specname);
    152  1.11       mrg 
    153  1.14     lukem 	/* d_type */
    154  1.11       mrg 	for (;;) {
    155  1.14     lukem 		i = lp->d_type;
    156  1.14     lukem 		if (i < 0 || i >= DKMAXTYPES)
    157  1.14     lukem 			i = 0;
    158  1.14     lukem 		snprintf(def, sizeof(def), "%s", dktypenames[i]);
    159  1.14     lukem 		i = getinput(":", "Disk type [?]", def, line);
    160  1.14     lukem 		if (i == -1)
    161  1.14     lukem 			return;
    162  1.14     lukem 		else if (i == 0)
    163  1.14     lukem 			break;
    164  1.14     lukem 		if (!strcmp(line, "?")) {
    165  1.14     lukem 			dumpnames("Supported disk types", dktypenames,
    166  1.14     lukem 			    DKMAXTYPES);
    167  1.14     lukem 			continue;
    168  1.14     lukem 		}
    169  1.14     lukem 		for (i = 0; i < DKMAXTYPES; i++) {
    170  1.14     lukem 			if (!strcasecmp(dktypenames[i], line)) {
    171  1.14     lukem 				lp->d_type = i;
    172  1.11       mrg 				goto done_typename;
    173  1.11       mrg 			}
    174  1.14     lukem 		}
    175  1.11       mrg 		v = atoi(line);
    176  1.11       mrg 		if ((unsigned)v >= DKMAXTYPES) {
    177  1.14     lukem 			warnx("Unknown disk type: %s", line);
    178  1.11       mrg 			continue;
    179  1.11       mrg 		}
    180  1.11       mrg 		lp->d_type = v;
    181  1.16     lukem  done_typename:
    182  1.11       mrg 		break;
    183  1.11       mrg 	}
    184  1.11       mrg 
    185  1.14     lukem 	/* d_typename */
    186  1.14     lukem 	snprintf(def, sizeof(def), "%.*s",
    187  1.14     lukem 	    (int) sizeof(lp->d_typename), lp->d_typename);
    188  1.14     lukem 	i = getinput(":", "Disk name", def, line);
    189  1.14     lukem 	if (i == -1)
    190  1.14     lukem 		return;
    191  1.14     lukem 	else if (i == 1)
    192  1.14     lukem 		(void) strncpy(lp->d_typename, line, sizeof(lp->d_typename));
    193  1.14     lukem 
    194  1.11       mrg 	/* d_packname */
    195  1.11       mrg 	cmd_name(lp, s, fd);
    196  1.11       mrg 
    197  1.11       mrg 	/* d_npartitions */
    198  1.11       mrg 	for (;;) {
    199  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_npartitions);
    200  1.11       mrg 		i = getinput(":", "Number of partitions", def, line);
    201  1.14     lukem 		if (i == -1)
    202  1.14     lukem 			return;
    203  1.14     lukem 		else if (i == 0)
    204  1.11       mrg 			break;
    205  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    206  1.14     lukem 			printf("Invalid number of partitions `%s'\n", line);
    207  1.11       mrg 			continue;
    208  1.11       mrg 		}
    209  1.11       mrg 		lp->d_npartitions = u;
    210  1.11       mrg 		break;
    211  1.11       mrg 	}
    212  1.11       mrg 
    213  1.11       mrg 	/* d_secsize */
    214  1.11       mrg 	for (;;) {
    215  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_secsize);
    216  1.11       mrg 		i = getinput(":", "Sector size (bytes)", def, line);
    217  1.14     lukem 		if (i == -1)
    218  1.14     lukem 			return;
    219  1.14     lukem 		else if (i == 0)
    220  1.11       mrg 			break;
    221  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    222  1.11       mrg 			printf("Invalid sector size `%s'\n", line);
    223  1.11       mrg 			continue;
    224  1.11       mrg 		}
    225  1.11       mrg 		lp->d_secsize = u;
    226  1.11       mrg 		break;
    227  1.11       mrg 	}
    228  1.11       mrg 
    229  1.11       mrg 	/* d_nsectors */
    230  1.11       mrg 	for (;;) {
    231  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_nsectors);
    232  1.11       mrg 		i = getinput(":", "Number of sectors per track", def, line);
    233  1.14     lukem 		if (i == -1)
    234  1.14     lukem 			return;
    235  1.14     lukem 		else if (i == 0)
    236  1.11       mrg 			break;
    237  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    238  1.14     lukem 			printf("Invalid number of sectors `%s'\n", line);
    239  1.11       mrg 			continue;
    240  1.11       mrg 		}
    241  1.11       mrg 		lp->d_nsectors = u;
    242  1.11       mrg 		break;
    243  1.11       mrg 	}
    244  1.11       mrg 
    245  1.11       mrg 	/* d_ntracks */
    246  1.11       mrg 	for (;;) {
    247  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_ntracks);
    248  1.11       mrg 		i = getinput(":", "Number of tracks per cylinder", def, line);
    249  1.14     lukem 		if (i == -1)
    250  1.14     lukem 			return;
    251  1.14     lukem 		else if (i == 0)
    252  1.11       mrg 			break;
    253  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    254  1.11       mrg 			printf("Invalid number of tracks `%s'\n", line);
    255  1.11       mrg 			continue;
    256  1.11       mrg 		}
    257  1.11       mrg 		lp->d_ntracks = u;
    258  1.11       mrg 		break;
    259  1.11       mrg 	}
    260  1.11       mrg 
    261  1.11       mrg 	/* d_secpercyl */
    262  1.11       mrg 	for (;;) {
    263  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_secpercyl);
    264  1.11       mrg 		i = getinput(":", "Number of sectors/cylinder", def, line);
    265  1.14     lukem 		if (i == -1)
    266  1.14     lukem 			return;
    267  1.14     lukem 		else if (i == 0)
    268  1.11       mrg 			break;
    269  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    270  1.14     lukem 			printf("Invalid number of sector/cylinder `%s'\n",
    271  1.14     lukem 			    line);
    272  1.11       mrg 			continue;
    273  1.11       mrg 		}
    274  1.11       mrg 		lp->d_secpercyl = u;
    275  1.11       mrg 		break;
    276  1.11       mrg 	}
    277  1.11       mrg 
    278  1.11       mrg 	/* d_ncylinders */
    279  1.11       mrg 	for (;;) {
    280  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_ncylinders);
    281  1.11       mrg 		i = getinput(":", "Total number of cylinders", def, line);
    282  1.14     lukem 		if (i == -1)
    283  1.14     lukem 			return;
    284  1.14     lukem 		else if (i == 0)
    285  1.11       mrg 			break;
    286  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    287  1.11       mrg 			printf("Invalid sector size `%s'\n", line);
    288  1.11       mrg 			continue;
    289  1.11       mrg 		}
    290  1.11       mrg 		lp->d_ncylinders = u;
    291  1.11       mrg 		break;
    292  1.11       mrg 	}
    293  1.11       mrg 
    294  1.11       mrg 	/* d_secperunit */
    295  1.11       mrg 	for (;;) {
    296  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_secperunit);
    297  1.11       mrg 		i = getinput(":", "Total number of sectors", def, line);
    298  1.14     lukem 		if (i == -1)
    299  1.14     lukem 			return;
    300  1.14     lukem 		else if (i == 0)
    301  1.11       mrg 			break;
    302  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    303  1.14     lukem 			printf("Invalid number of sectors `%s'\n", line);
    304  1.11       mrg 			continue;
    305  1.11       mrg 		}
    306  1.11       mrg 		lp->d_secperunit = u;
    307  1.11       mrg 		break;
    308  1.11       mrg 	}
    309  1.11       mrg 
    310  1.11       mrg 	/* d_rpm */
    311  1.11       mrg 
    312  1.11       mrg 	/* d_interleave */
    313  1.11       mrg 	for (;;) {
    314  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_interleave);
    315  1.11       mrg 		i = getinput(":", "Hardware sectors interleave", def, line);
    316  1.14     lukem 		if (i == -1)
    317  1.14     lukem 			return;
    318  1.14     lukem 		else if (i == 0)
    319  1.11       mrg 			break;
    320  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    321  1.14     lukem 			printf("Invalid sector interleave `%s'\n", line);
    322  1.11       mrg 			continue;
    323  1.11       mrg 		}
    324  1.11       mrg 		lp->d_interleave = u;
    325  1.11       mrg 		break;
    326  1.11       mrg 	}
    327  1.11       mrg 
    328  1.11       mrg 	/* d_trackskew */
    329  1.11       mrg 	for (;;) {
    330  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_trackskew);
    331  1.11       mrg 		i = getinput(":", "Sector 0 skew, per track", def, line);
    332  1.14     lukem 		if (i == -1)
    333  1.14     lukem 			return;
    334  1.14     lukem 		else if (i == 0)
    335  1.11       mrg 			break;
    336  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    337  1.14     lukem 			printf("Invalid track sector skew `%s'\n", line);
    338  1.11       mrg 			continue;
    339  1.11       mrg 		}
    340  1.11       mrg 		lp->d_trackskew = u;
    341  1.11       mrg 		break;
    342  1.11       mrg 	}
    343  1.11       mrg 
    344  1.11       mrg 	/* d_cylskew */
    345  1.11       mrg 	for (;;) {
    346  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_cylskew);
    347  1.11       mrg 		i = getinput(":", "Sector 0 skew, per cylinder", def, line);
    348  1.14     lukem 		if (i == -1)
    349  1.14     lukem 			return;
    350  1.14     lukem 		else if (i == 0)
    351  1.11       mrg 			break;
    352  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    353  1.14     lukem 			printf("Invalid cylinder sector `%s'\n", line);
    354  1.11       mrg 			continue;
    355  1.11       mrg 		}
    356  1.11       mrg 		lp->d_cylskew = u;
    357  1.11       mrg 		break;
    358  1.11       mrg 	}
    359  1.11       mrg 
    360  1.11       mrg 	/* d_headswitch */
    361  1.11       mrg 	for (;;) {
    362  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_headswitch);
    363  1.11       mrg 		i = getinput(":", "Head switch time (usec)", def, line);
    364  1.14     lukem 		if (i == -1)
    365  1.14     lukem 			return;
    366  1.14     lukem 		else if (i == 0)
    367  1.11       mrg 			break;
    368  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    369  1.14     lukem 			printf("Invalid head switch time `%s'\n", line);
    370  1.11       mrg 			continue;
    371  1.11       mrg 		}
    372  1.11       mrg 		lp->d_headswitch = u;
    373  1.11       mrg 		break;
    374  1.11       mrg 	}
    375  1.11       mrg 
    376  1.11       mrg 	/* d_trkseek */
    377  1.11       mrg 	for (;;) {
    378  1.14     lukem 		snprintf(def, sizeof(def), "%u", lp->d_trkseek);
    379  1.11       mrg 		i = getinput(":", "Track seek time (usec)", def, line);
    380  1.14     lukem 		if (i == -1)
    381  1.14     lukem 			return;
    382  1.14     lukem 		else if (i == 0)
    383  1.11       mrg 			break;
    384  1.11       mrg 		if (sscanf(line, "%u", &u) != 1) {
    385  1.14     lukem 			printf("Invalid track seek time `%s'\n", line);
    386  1.11       mrg 			continue;
    387  1.11       mrg 		}
    388  1.11       mrg 		lp->d_trkseek = u;
    389  1.11       mrg 		break;
    390  1.11       mrg 	}
    391  1.11       mrg }
    392   1.1  christos 
    393  1.16     lukem 
    394   1.1  christos static void
    395  1.16     lukem cmd_name(struct disklabel *lp, char *s, int fd)
    396  1.16     lukem {
    397  1.16     lukem 	char	line[BUFSIZ];
    398  1.16     lukem 	char	def[BUFSIZ];
    399  1.16     lukem 	int	i;
    400   1.1  christos 
    401  1.15     lukem 	snprintf(def, sizeof(def), "%.*s",
    402  1.14     lukem 	    (int) sizeof(lp->d_packname), lp->d_packname);
    403  1.15     lukem 	i = getinput(":", "Label name", def, line);
    404   1.1  christos 	if (i <= 0)
    405   1.1  christos 		return;
    406   1.1  christos 	(void) strncpy(lp->d_packname, line, sizeof(lp->d_packname));
    407   1.1  christos }
    408   1.1  christos 
    409  1.16     lukem 
    410   1.1  christos static void
    411  1.16     lukem cmd_round(struct disklabel *lp, char *s, int fd)
    412   1.1  christos {
    413  1.16     lukem 	int	i;
    414  1.16     lukem 	char	line[BUFSIZ];
    415   1.1  christos 
    416   1.1  christos 	i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line);
    417   1.1  christos 	if (i <= 0)
    418   1.1  christos 		return;
    419   1.1  christos 
    420   1.1  christos 	switch (line[0]) {
    421   1.1  christos 	case 'c':
    422   1.1  christos 		rounding = 1;
    423   1.1  christos 		return;
    424   1.1  christos 	case 's':
    425   1.1  christos 		rounding = 0;
    426   1.1  christos 		return;
    427   1.1  christos 	default:
    428   1.1  christos 		printf("Rounding can be (c)ylinders or (s)ectors\n");
    429   1.1  christos 		return;
    430   1.1  christos 	}
    431   1.1  christos }
    432   1.1  christos 
    433  1.16     lukem 
    434   1.1  christos static void
    435  1.16     lukem cmd_part(struct disklabel *lp, char *s, int fd)
    436  1.16     lukem {
    437  1.16     lukem 	int	i;
    438  1.16     lukem 	char	line[BUFSIZ];
    439  1.16     lukem 	char	def[BUFSIZ];
    440  1.16     lukem 	int	part;
    441  1.16     lukem 	struct partition *p;
    442   1.1  christos 
    443  1.16     lukem 	part = s[0] - 'a';
    444  1.16     lukem 	p = &lp->d_partitions[part];
    445   1.4  christos 	if (part >= lp->d_npartitions)
    446   1.1  christos 		lp->d_npartitions = part + 1;
    447   1.1  christos 
    448   1.1  christos 	for (;;) {
    449  1.14     lukem 		i = p->p_fstype;
    450  1.14     lukem 		if (i < 0 || i >= FSMAXTYPES)
    451  1.14     lukem 			i = 0;
    452  1.14     lukem 		snprintf(def, sizeof(def), "%s", fstypenames[i]);
    453  1.14     lukem 		i = getinput(":", "Filesystem type [?]", def, line);
    454  1.14     lukem 		if (i == -1)
    455  1.14     lukem 			return;
    456  1.14     lukem 		else if (i == 0)
    457  1.14     lukem 			break;
    458  1.14     lukem 		if (!strcmp(line, "?")) {
    459  1.14     lukem 			dumpnames("Supported file system types",
    460  1.14     lukem 			    fstypenames, FSMAXTYPES);
    461  1.14     lukem 			continue;
    462  1.14     lukem 		}
    463  1.14     lukem 		for (i = 0; i < FSMAXTYPES; i++)
    464  1.14     lukem 			if (!strcasecmp(line, fstypenames[i])) {
    465  1.14     lukem 				p->p_fstype = i;
    466  1.14     lukem 				goto done_typename;
    467  1.14     lukem 			}
    468  1.14     lukem 		printf("Invalid file system typename `%s'\n", line);
    469  1.14     lukem 		continue;
    470  1.16     lukem  done_typename:
    471   1.1  christos 		break;
    472   1.1  christos 	}
    473   1.1  christos 	for (;;) {
    474  1.16     lukem 		defnum(lp, def, p->p_offset);
    475   1.1  christos 		i = getinput(":", "Start offset", def, line);
    476  1.14     lukem 		if (i == -1)
    477  1.14     lukem 			return;
    478  1.14     lukem 		else if (i == 0)
    479   1.1  christos 			break;
    480  1.16     lukem 		if ((i = getnum(lp, line, 0)) == -1) {
    481   1.1  christos 			printf("Bad offset `%s'\n", line);
    482   1.1  christos 			continue;
    483   1.1  christos 		}
    484   1.1  christos 		p->p_offset = i;
    485   1.1  christos 		break;
    486   1.1  christos 	}
    487   1.1  christos 	for (;;) {
    488  1.16     lukem 		defnum(lp, def, p->p_size);
    489  1.13       abs 		i = getinput(":", "Partition size ('$' for all remaining)",
    490  1.12       abs 		    def, line);
    491  1.14     lukem 		if (i == -1)
    492  1.14     lukem 			return;
    493  1.14     lukem 		else if (i == 0)
    494   1.1  christos 			break;
    495  1.16     lukem 		if ((i = getnum(lp, line, lp->d_secperunit - p->p_offset))
    496  1.12       abs 		    == -1) {
    497   1.1  christos 			printf("Bad size `%s'\n", line);
    498   1.1  christos 			continue;
    499   1.1  christos 		}
    500   1.1  christos 		p->p_size = i;
    501   1.1  christos 		break;
    502   1.9  christos 	}
    503   1.9  christos 
    504   1.9  christos 	if (chaining) {
    505   1.9  christos 		int offs = p[0].p_offset + p[0].p_size;
    506   1.9  christos 		p = lp->d_partitions;
    507   1.9  christos 		part = getrawpartition();
    508   1.9  christos 		for (i = 1; i < lp->d_npartitions; i++) {
    509   1.9  christos 			if (i != part && p[i].p_fstype) {
    510   1.9  christos 				p[i].p_offset = offs;
    511   1.9  christos 				offs = p[i].p_offset + p[i].p_size;
    512   1.9  christos 			}
    513   1.9  christos 		}
    514   1.1  christos 	}
    515   1.1  christos }
    516   1.1  christos 
    517   1.1  christos 
    518   1.1  christos static void
    519  1.16     lukem cmd_label(struct disklabel *lp, char *s, int fd)
    520   1.1  christos {
    521  1.16     lukem 	char	line[BUFSIZ];
    522  1.16     lukem 	int	i;
    523   1.1  christos 
    524   1.1  christos 	i = getinput("?", "Label disk", "n", line);
    525  1.10       abs 	if (i <= 0 || (*line != 'y' && *line != 'Y') )
    526   1.1  christos 		return;
    527   1.1  christos 
    528   1.1  christos 	if (checklabel(lp) != 0) {
    529   1.1  christos 		printf("Label not written\n");
    530   1.1  christos 		return;
    531   1.1  christos 	}
    532   1.1  christos 
    533   1.6     enami 	if (writelabel(fd, bootarea, lp) != 0) {
    534   1.6     enami 		printf("Label not written\n");
    535   1.1  christos 		return;
    536   1.1  christos 	}
    537   1.1  christos 	printf("Label written\n");
    538   1.1  christos }
    539   1.1  christos 
    540   1.1  christos 
    541   1.1  christos static int
    542  1.16     lukem runcmd(struct disklabel *lp, char *line, int fd)
    543   1.1  christos {
    544   1.1  christos 	struct cmds *cmd;
    545   1.1  christos 
    546   1.1  christos 	for (cmd = cmds; cmd->name != NULL; cmd++)
    547   1.1  christos 		if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
    548   1.1  christos 			if (cmd->func == NULL)
    549   1.1  christos 				return -1;
    550   1.1  christos 			(*cmd->func)(lp, line, fd);
    551   1.5  christos 			return 0;
    552   1.1  christos 		}
    553   1.2  christos 
    554   1.2  christos 	if (line[1] == '\0' &&
    555   1.2  christos 	    line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
    556   1.2  christos 		cmd_part(lp, line, fd);
    557   1.5  christos 		return 0;
    558   1.2  christos 	}
    559   1.2  christos 
    560   1.1  christos 	printf("Unknown command %s\n", line);
    561   1.5  christos 	return 1;
    562   1.1  christos }
    563   1.1  christos 
    564   1.1  christos 
    565   1.1  christos static int
    566  1.16     lukem getinput(const char *sep, const char *prompt, const char *def, char *line)
    567   1.1  christos {
    568  1.16     lukem 
    569   1.1  christos 	for (;;) {
    570   1.1  christos 		printf("%s", prompt);
    571   1.1  christos 		if (def)
    572   1.1  christos 			printf(" [%s]", def);
    573   1.1  christos 		printf("%s ", sep);
    574   1.1  christos 
    575   1.1  christos 		if (fgets(line, BUFSIZ, stdin) == NULL)
    576   1.1  christos 			return -1;
    577   1.1  christos 		if (line[0] == '\n' || line[0] == '\0') {
    578   1.1  christos 			if (def)
    579   1.1  christos 				return 0;
    580   1.1  christos 		}
    581   1.1  christos 		else {
    582   1.1  christos 			char *p;
    583   1.1  christos 
    584   1.1  christos 			if ((p = strrchr(line, '\n')) != NULL)
    585   1.1  christos 				*p = '\0';
    586   1.1  christos 			return 1;
    587   1.1  christos 		}
    588   1.1  christos 	}
    589   1.1  christos }
    590   1.1  christos 
    591  1.14     lukem static int
    592  1.16     lukem alphacmp(const void *a, const void *b)
    593  1.14     lukem {
    594  1.14     lukem 
    595  1.14     lukem 	return (strcasecmp(*(const char **)a, *(const char **)b));
    596  1.14     lukem }
    597  1.14     lukem 
    598  1.14     lukem 
    599  1.14     lukem static void
    600  1.16     lukem dumpnames(const char *prompt, const char * const *olist, size_t numentries)
    601  1.14     lukem {
    602  1.16     lukem 	int	i, j, w;
    603  1.16     lukem 	int	columns, width, lines;
    604  1.14     lukem 	const char *p;
    605  1.14     lukem 	const char **list;
    606  1.14     lukem 
    607  1.14     lukem 	list = (const char **)malloc(sizeof(char *) * numentries);
    608  1.14     lukem 	width = 0;
    609  1.14     lukem 	printf("%s:\n", prompt);
    610  1.14     lukem 	for (i = 0; i < numentries; i++) {
    611  1.14     lukem 		list[i] = olist[i];
    612  1.14     lukem 		w = strlen(list[i]);
    613  1.14     lukem 		if (w > width)
    614  1.14     lukem 			width = w;
    615  1.14     lukem 	}
    616  1.14     lukem #if 0
    617  1.14     lukem 	for (i = 0; i < numentries; i++)
    618  1.14     lukem 		printf("%s%s", i == 0 ? "" : ", ", list[i]);
    619  1.14     lukem 	puts("");
    620  1.14     lukem #endif
    621  1.14     lukem 	(void)qsort((void *)list, numentries, sizeof(char *), alphacmp);
    622  1.14     lukem 	width++;		/* want two spaces between items */
    623  1.14     lukem 	width = (width + 8) &~ 7;
    624  1.14     lukem 
    625  1.14     lukem #define ttywidth 72
    626  1.14     lukem 	columns = ttywidth / width;
    627  1.14     lukem #undef ttywidth
    628  1.14     lukem 	if (columns == 0)
    629  1.14     lukem 		columns = 1;
    630  1.14     lukem 	lines = (numentries + columns - 1) / columns;
    631  1.14     lukem 	for (i = 0; i < lines; i++) {
    632  1.14     lukem 		for (j = 0; j < columns; j++) {
    633  1.14     lukem 			p = list[j * lines + i];
    634  1.14     lukem 			if (j == 0)
    635  1.14     lukem 				putc('\t', stdout);
    636  1.14     lukem 			if (p) {
    637  1.14     lukem 				fputs(p, stdout);
    638  1.14     lukem 			}
    639  1.14     lukem 			if (j * lines + i + lines >= numentries) {
    640  1.14     lukem 				putc('\n', stdout);
    641  1.14     lukem 				break;
    642  1.14     lukem 			}
    643  1.14     lukem 			w = strlen(p);
    644  1.14     lukem 			while (w < width) {
    645  1.14     lukem 				w = (w + 8) &~ 7;
    646  1.14     lukem 				putc('\t', stdout);
    647  1.14     lukem 			}
    648  1.14     lukem 		}
    649  1.14     lukem 	}
    650  1.14     lukem 	free(list);
    651  1.14     lukem }
    652  1.14     lukem 
    653   1.1  christos 
    654   1.1  christos static void
    655  1.16     lukem defnum(struct disklabel *lp, char *buf, int size)
    656   1.1  christos {
    657  1.16     lukem 
    658   1.1  christos 	(void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM",
    659   1.1  christos 	    size / (float) lp->d_secpercyl,
    660   1.1  christos 	    size, size  * (lp->d_secsize / (float) (1024 * 1024)));
    661   1.1  christos }
    662   1.1  christos 
    663   1.1  christos 
    664   1.1  christos static int
    665  1.16     lukem getnum(struct disklabel *lp, char *buf, int max)
    666  1.16     lukem {
    667  1.16     lukem 	char	*ep;
    668  1.16     lukem 	double	 d;
    669  1.16     lukem 	int	 rv;
    670   1.1  christos 
    671  1.13       abs 	if (max && buf[0] == '$' && buf[1] == 0)
    672  1.12       abs 		return max;
    673  1.12       abs 
    674  1.12       abs 	d = strtod(buf, &ep);
    675   1.1  christos 	if (buf == ep)
    676   1.1  christos 		return -1;
    677   1.1  christos 
    678  1.16     lukem #define ROUND(a)	((((a) / lp->d_secpercyl) + \
    679  1.16     lukem 		 	 (((a) % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl)
    680   1.1  christos 
    681   1.1  christos 	switch (*ep) {
    682   1.1  christos 	case '\0':
    683   1.1  christos 	case 's':
    684   1.1  christos 		rv = (int) d;
    685   1.1  christos 		break;
    686   1.1  christos 
    687   1.1  christos 	case 'c':
    688   1.1  christos 		rv = (int) (d * lp->d_secpercyl);
    689   1.1  christos 		break;
    690   1.1  christos 
    691  1.14     lukem 	case 'm':
    692   1.1  christos 	case 'M':
    693   1.1  christos 		rv =  (int) (d * 1024 * 1024 / lp->d_secsize);
    694   1.1  christos 		break;
    695   1.1  christos 
    696   1.1  christos 	default:
    697   1.1  christos 		printf("Unit error %c\n", *ep);
    698   1.1  christos 		return -1;
    699   1.1  christos 	}
    700   1.1  christos 
    701   1.1  christos 	if (rounding)
    702   1.1  christos 		return ROUND(rv);
    703   1.1  christos 	else
    704   1.1  christos 		return rv;
    705   1.1  christos }
    706   1.1  christos 
    707   1.1  christos 
    708   1.1  christos void
    709  1.16     lukem interact(struct disklabel *lp, int fd)
    710   1.1  christos {
    711  1.16     lukem 	char	line[BUFSIZ];
    712   1.1  christos 
    713   1.1  christos 	for (;;) {
    714   1.1  christos 		if (getinput(">", "partition", NULL, line) == -1)
    715   1.1  christos 			return;
    716  1.16     lukem 		if (runcmd(lp, line, fd) == -1)
    717   1.1  christos 			return;
    718   1.1  christos 	}
    719   1.1  christos }
    720