Home | History | Annotate | Line # | Download | only in disklabel
interact.c revision 1.1
      1 /*	$NetBSD: interact.c,v 1.1 1997/03/08 23:46:12 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Christos Zoulas.
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef lint
     33 static char rcsid[] = "$NetBSD: interact.c,v 1.1 1997/03/08 23:46:12 christos Exp $";
     34 #endif /* lint */
     35 
     36 #include <stdio.h>
     37 #include <string.h>
     38 #include <stdlib.h>
     39 #include <sys/types.h>
     40 #include <sys/param.h>
     41 #define DKTYPENAMES
     42 #include <sys/disklabel.h>
     43 
     44 #include "extern.h"
     45 
     46 static void cmd_help __P((struct disklabel *, char *, int));
     47 static void cmd_print __P((struct disklabel *, char *, int));
     48 static void cmd_part __P((struct disklabel *, char *, int));
     49 static void cmd_label __P((struct disklabel *, char *, int));
     50 static void cmd_round __P((struct disklabel *, char *, int));
     51 static void cmd_name __P((struct disklabel *, char *, int));
     52 static int runcmd __P((char *, struct disklabel *, int));
     53 static int getinput __P((const char *, const char *, const char *, char *));
     54 static void defnum __P((char *, struct disklabel *, int));
     55 static int getnum __P((char *, struct disklabel *));
     56 static void deffstypename __P((char *, int));
     57 static int getfstypename __P((const char *));
     58 
     59 static int rounding = 0;	/* sector rounding */
     60 
     61 static struct cmds {
     62 	const char *name;
     63 	void (*func) __P((struct disklabel *, char *, int));
     64 	const char *help;
     65 } cmds[] = {
     66 	{ "a",	cmd_part,	"define partition a" },
     67 	{ "b",	cmd_part,	"define partition b" },
     68 	{ "c",	cmd_part,	"define partition c" },
     69 	{ "d",	cmd_part,	"define partition d" },
     70 	{ "e",	cmd_part,	"define partition e" },
     71 	{ "f",	cmd_part,	"define partition f" },
     72 	{ "g",	cmd_part,	"define partition g" },
     73 	{ "h",	cmd_part,	"define partition h" },
     74 	{ "l",	cmd_label,	"write the current partition table" },
     75 	{ "n",	cmd_name,	"name the label" },
     76 	{ "p",	cmd_print,	"print current partition table" },
     77 	{ "q",	NULL,		"quit" },
     78 	{ "r",	cmd_round,	"rounding (c)ylinders (s)ectors" },
     79 	{ "?",	cmd_help,	"print this menu" },
     80 	{ NULL, NULL,		NULL }
     81 };
     82 
     83 
     84 
     85 static void
     86 cmd_help(lp, s, fd)
     87 	struct disklabel *lp;
     88 	char *s;
     89 	int fd;
     90 {
     91 	struct cmds *cmd;
     92 	for (cmd = cmds; cmd->name != NULL; cmd++)
     93 		printf("%s\t%s\n", cmd->name, cmd->help);
     94 }
     95 
     96 
     97 static void
     98 cmd_print(lp, s, fd)
     99 	struct disklabel *lp;
    100 	char *s;
    101 	int fd;
    102 {
    103 	display(stdout, lp);
    104 }
    105 
    106 
    107 static void
    108 cmd_name(lp, s, fd)
    109 	struct disklabel *lp;
    110 	char *s;
    111 	int fd;
    112 {
    113 	char line[BUFSIZ];
    114 	int i = getinput(":", "Label name", lp->d_packname, line);
    115 
    116 	if (i <= 0)
    117 		return;
    118 	(void) strncpy(lp->d_packname, line, sizeof(lp->d_packname));
    119 }
    120 
    121 
    122 static void
    123 cmd_round(lp, s, fd)
    124 	struct disklabel *lp;
    125 	char *s;
    126 	int fd;
    127 {
    128 	int i;
    129 	char line[BUFSIZ];
    130 
    131 	i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line);
    132 
    133 	if (i <= 0)
    134 		return;
    135 
    136 	switch (line[0]) {
    137 	case 'c':
    138 		rounding = 1;
    139 		return;
    140 	case 's':
    141 		rounding = 0;
    142 		return;
    143 	default:
    144 		printf("Rounding can be (c)ylinders or (s)ectors\n");
    145 		return;
    146 	}
    147 }
    148 
    149 
    150 static void
    151 cmd_part(lp, s, fd)
    152 	struct disklabel *lp;
    153 	char *s;
    154 	int fd;
    155 {
    156 	int i;
    157 	char line[BUFSIZ];
    158 	char def[BUFSIZ];
    159 	int part = *s - 'a';
    160 	struct partition *p = &lp->d_partitions[part];
    161 
    162 	if (part <= lp->d_npartitions)
    163 		lp->d_npartitions = part + 1;
    164 
    165 	for (;;) {
    166 		deffstypename(def, p->p_fstype);
    167 		i = getinput(":", "Filesystem type", def, line);
    168 		if (i <= 0)
    169 			break;
    170 		if ((i = getfstypename(line)) == -1) {
    171 			printf("Invalid file system typename `%s'\n", line);
    172 			continue;
    173 		}
    174 		p->p_fstype = i;
    175 		break;
    176 	}
    177 	for (;;) {
    178 		defnum(def, lp, p->p_offset);
    179 		i = getinput(":", "Start offset", def, line);
    180 		if (i <= 0)
    181 			break;
    182 		if ((i = getnum(line, lp)) == -1) {
    183 			printf("Bad offset `%s'\n", line);
    184 			continue;
    185 		}
    186 		p->p_offset = i;
    187 		break;
    188 	}
    189 	for (;;) {
    190 		defnum(def, lp, p->p_size);
    191 		i = getinput(":", "Partition size", def, line);
    192 		if (i <= 0)
    193 			break;
    194 		if ((i = getnum(line, lp)) == -1) {
    195 			printf("Bad size `%s'\n", line);
    196 			continue;
    197 		}
    198 		p->p_size = i;
    199 		break;
    200 	}
    201 }
    202 
    203 
    204 static void
    205 cmd_label(lp, s, fd)
    206 	struct disklabel *lp;
    207 	char *s;
    208 	int fd;
    209 {
    210 	char line[BUFSIZ];
    211 	int i;
    212 
    213 	i = getinput("?", "Label disk", "n", line);
    214 
    215 	if (i <= 0 || *line != 'y')
    216 		return;
    217 
    218 	if (checklabel(lp) != 0) {
    219 		printf("Label not written\n");
    220 		return;
    221 	}
    222 
    223 	if ((i = writelabel(fd, bootarea, lp)) != 0) {
    224 		printf("Label not written %d\n", strerror(i));
    225 		return;
    226 	}
    227 	printf("Label written\n");
    228 }
    229 
    230 
    231 static int
    232 runcmd(line, lp, fd)
    233 	char *line;
    234 	struct disklabel *lp;
    235 	int fd;
    236 {
    237 	struct cmds *cmd;
    238 
    239 	for (cmd = cmds; cmd->name != NULL; cmd++)
    240 		if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
    241 			if (cmd->func == NULL)
    242 				return -1;
    243 			(*cmd->func)(lp, line, fd);
    244 			return;
    245 		}
    246 	printf("Unknown command %s\n", line);
    247 }
    248 
    249 
    250 static int
    251 getinput(sep, prompt, def, line)
    252 	const char *sep;
    253 	const char *prompt;
    254 	const char *def;
    255 	char *line;
    256 {
    257 	for (;;) {
    258 		printf("%s", prompt);
    259 		if (def)
    260 			printf(" [%s]", def);
    261 		printf("%s ", sep);
    262 
    263 		if (fgets(line, BUFSIZ, stdin) == NULL)
    264 			return -1;
    265 		if (line[0] == '\n' || line[0] == '\0') {
    266 			if (def)
    267 				return 0;
    268 		}
    269 		else {
    270 			char *p;
    271 
    272 			if ((p = strrchr(line, '\n')) != NULL)
    273 				*p = '\0';
    274 			return 1;
    275 		}
    276 	}
    277 }
    278 
    279 
    280 static void
    281 defnum(buf, lp, size)
    282 	char *buf;
    283 	struct disklabel *lp;
    284 	int size;
    285 {
    286 	(void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM",
    287 	    size / (float) lp->d_secpercyl,
    288 	    size, size  * (lp->d_secsize / (float) (1024 * 1024)));
    289 }
    290 
    291 
    292 static int
    293 getnum(buf, lp)
    294 	char *buf;
    295 	struct disklabel *lp;
    296 {
    297 	char *ep;
    298 	double d = strtod(buf, &ep);
    299 	int rv;
    300 
    301 	if (buf == ep)
    302 		return -1;
    303 
    304 #define ROUND(a)	((a / lp->d_secpercyl) + \
    305 			 ((a % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl
    306 
    307 	switch (*ep) {
    308 	case '\0':
    309 	case 's':
    310 		rv = (int) d;
    311 		break;
    312 
    313 	case 'c':
    314 		rv = (int) (d * lp->d_secpercyl);
    315 		break;
    316 
    317 	case 'M':
    318 		rv =  (int) (d * 1024 * 1024 / lp->d_secsize);
    319 		break;
    320 
    321 	default:
    322 		printf("Unit error %c\n", *ep);
    323 		return -1;
    324 	}
    325 
    326 	if (rounding)
    327 		return ROUND(rv);
    328 	else
    329 		return rv;
    330 }
    331 
    332 
    333 static void
    334 deffstypename(buf, i)
    335 	char *buf;
    336 	int i;
    337 {
    338 	if (i < 0 || i >= DKMAXTYPES)
    339 		i = 0;
    340 	(void) strcpy(buf, fstypenames[i]);
    341 }
    342 
    343 
    344 static int
    345 getfstypename(buf)
    346 	const char *buf;
    347 {
    348 	int i;
    349 
    350 	for (i = 0; i < DKMAXTYPES; i++)
    351 		if (strcmp(buf, fstypenames[i]) == 0)
    352 			return i;
    353 	return -1;
    354 }
    355 
    356 
    357 void
    358 interact(lp, fd)
    359 	struct disklabel *lp;
    360 	int fd;
    361 {
    362 	char line[BUFSIZ];
    363 
    364 	for (;;) {
    365 		if (getinput(">", "partition", NULL, line) == -1)
    366 			return;
    367 		if (runcmd(line, lp, fd) == -1)
    368 			return;
    369 	}
    370 }
    371