1 /* $NetBSD: interact.c,v 1.8 1998/11/12 16:19:48 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 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: interact.c,v 1.8 1998/11/12 16:19:48 christos Exp $"); 35 #endif /* lint */ 36 37 #include <stdio.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include <util.h> 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #define FSTYPENAMES 44 #include <sys/disklabel.h> 45 46 #include "extern.h" 47 48 static void cmd_help __P((struct disklabel *, char *, int)); 49 static void cmd_print __P((struct disklabel *, char *, int)); 50 static void cmd_part __P((struct disklabel *, char *, int)); 51 static void cmd_label __P((struct disklabel *, char *, int)); 52 static void cmd_round __P((struct disklabel *, char *, int)); 53 static void cmd_name __P((struct disklabel *, char *, int)); 54 static int runcmd __P((char *, struct disklabel *, int)); 55 static int getinput __P((const char *, const char *, const char *, char *)); 56 static void defnum __P((char *, struct disklabel *, int)); 57 static int getnum __P((char *, struct disklabel *)); 58 static void deffstypename __P((char *, int)); 59 static int getfstypename __P((const char *)); 60 61 static int rounding = 0; /* sector rounding */ 62 63 static struct cmds { 64 const char *name; 65 void (*func) __P((struct disklabel *, char *, int)); 66 const char *help; 67 } cmds[] = { 68 { "?", cmd_help, "print this menu" }, 69 { "N", cmd_name, "name the label" }, 70 { "P", cmd_print, "print current partition table" }, 71 { "Q", NULL, "quit" }, 72 { "R", cmd_round, "rounding (c)ylinders (s)ectors" }, 73 { "W", cmd_label, "write the current partition table" }, 74 { NULL, NULL, NULL } 75 }; 76 77 78 79 static void 80 cmd_help(lp, s, fd) 81 struct disklabel *lp; 82 char *s; 83 int fd; 84 { 85 struct cmds *cmd; 86 87 for (cmd = cmds; cmd->name != NULL; cmd++) 88 printf("%s\t%s\n", cmd->name, cmd->help); 89 printf("[a-%c]\tdefine named partition\n", 90 'a' + getmaxpartitions() - 1); 91 } 92 93 94 static void 95 cmd_print(lp, s, fd) 96 struct disklabel *lp; 97 char *s; 98 int fd; 99 { 100 display(stdout, lp); 101 } 102 103 104 static void 105 cmd_name(lp, s, fd) 106 struct disklabel *lp; 107 char *s; 108 int fd; 109 { 110 char line[BUFSIZ]; 111 int i = getinput(":", "Label name", lp->d_packname, line); 112 113 if (i <= 0) 114 return; 115 (void) strncpy(lp->d_packname, line, sizeof(lp->d_packname)); 116 } 117 118 119 static void 120 cmd_round(lp, s, fd) 121 struct disklabel *lp; 122 char *s; 123 int fd; 124 { 125 int i; 126 char line[BUFSIZ]; 127 128 i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line); 129 130 if (i <= 0) 131 return; 132 133 switch (line[0]) { 134 case 'c': 135 rounding = 1; 136 return; 137 case 's': 138 rounding = 0; 139 return; 140 default: 141 printf("Rounding can be (c)ylinders or (s)ectors\n"); 142 return; 143 } 144 } 145 146 147 static void 148 cmd_part(lp, s, fd) 149 struct disklabel *lp; 150 char *s; 151 int fd; 152 { 153 int i; 154 char line[BUFSIZ]; 155 char def[BUFSIZ]; 156 int part = *s - 'a'; 157 struct partition *p = &lp->d_partitions[part]; 158 159 if (part >= lp->d_npartitions) 160 lp->d_npartitions = part + 1; 161 162 for (;;) { 163 deffstypename(def, p->p_fstype); 164 i = getinput(":", "Filesystem type", def, line); 165 if (i <= 0) 166 break; 167 if ((i = getfstypename(line)) == -1) { 168 printf("Invalid file system typename `%s'\n", line); 169 continue; 170 } 171 p->p_fstype = i; 172 break; 173 } 174 for (;;) { 175 defnum(def, lp, p->p_offset); 176 i = getinput(":", "Start offset", def, line); 177 if (i <= 0) 178 break; 179 if ((i = getnum(line, lp)) == -1) { 180 printf("Bad offset `%s'\n", line); 181 continue; 182 } 183 p->p_offset = i; 184 break; 185 } 186 for (;;) { 187 defnum(def, lp, p->p_size); 188 i = getinput(":", "Partition size", def, line); 189 if (i <= 0) 190 break; 191 if ((i = getnum(line, lp)) == -1) { 192 printf("Bad size `%s'\n", line); 193 continue; 194 } 195 p->p_size = i; 196 break; 197 } 198 } 199 200 201 static void 202 cmd_label(lp, s, fd) 203 struct disklabel *lp; 204 char *s; 205 int fd; 206 { 207 char line[BUFSIZ]; 208 int i; 209 210 i = getinput("?", "Label disk", "n", line); 211 212 if (i <= 0 || *line != 'y') 213 return; 214 215 if (checklabel(lp) != 0) { 216 printf("Label not written\n"); 217 return; 218 } 219 220 if (writelabel(fd, bootarea, lp) != 0) { 221 printf("Label not written\n"); 222 return; 223 } 224 printf("Label written\n"); 225 } 226 227 228 static int 229 runcmd(line, lp, fd) 230 char *line; 231 struct disklabel *lp; 232 int fd; 233 { 234 struct cmds *cmd; 235 236 for (cmd = cmds; cmd->name != NULL; cmd++) 237 if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) { 238 if (cmd->func == NULL) 239 return -1; 240 (*cmd->func)(lp, line, fd); 241 return 0; 242 } 243 244 if (line[1] == '\0' && 245 line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) { 246 cmd_part(lp, line, fd); 247 return 0; 248 } 249 250 printf("Unknown command %s\n", line); 251 return 1; 252 } 253 254 255 static int 256 getinput(sep, prompt, def, line) 257 const char *sep; 258 const char *prompt; 259 const char *def; 260 char *line; 261 { 262 for (;;) { 263 printf("%s", prompt); 264 if (def) 265 printf(" [%s]", def); 266 printf("%s ", sep); 267 268 if (fgets(line, BUFSIZ, stdin) == NULL) 269 return -1; 270 if (line[0] == '\n' || line[0] == '\0') { 271 if (def) 272 return 0; 273 } 274 else { 275 char *p; 276 277 if ((p = strrchr(line, '\n')) != NULL) 278 *p = '\0'; 279 return 1; 280 } 281 } 282 } 283 284 285 static void 286 defnum(buf, lp, size) 287 char *buf; 288 struct disklabel *lp; 289 int size; 290 { 291 (void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM", 292 size / (float) lp->d_secpercyl, 293 size, size * (lp->d_secsize / (float) (1024 * 1024))); 294 } 295 296 297 static int 298 getnum(buf, lp) 299 char *buf; 300 struct disklabel *lp; 301 { 302 char *ep; 303 double d = strtod(buf, &ep); 304 int rv; 305 306 if (buf == ep) 307 return -1; 308 309 #define ROUND(a) ((a / lp->d_secpercyl) + \ 310 ((a % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl 311 312 switch (*ep) { 313 case '\0': 314 case 's': 315 rv = (int) d; 316 break; 317 318 case 'c': 319 rv = (int) (d * lp->d_secpercyl); 320 break; 321 322 case 'M': 323 rv = (int) (d * 1024 * 1024 / lp->d_secsize); 324 break; 325 326 default: 327 printf("Unit error %c\n", *ep); 328 return -1; 329 } 330 331 if (rounding) 332 return ROUND(rv); 333 else 334 return rv; 335 } 336 337 338 static void 339 deffstypename(buf, i) 340 char *buf; 341 int i; 342 { 343 if (i < 0 || i >= FSMAXTYPES) 344 i = 0; 345 (void) strcpy(buf, fstypenames[i]); 346 } 347 348 349 static int 350 getfstypename(buf) 351 const char *buf; 352 { 353 int i; 354 355 for (i = 0; i < FSMAXTYPES; i++) 356 if (strcmp(buf, fstypenames[i]) == 0) 357 return i; 358 return -1; 359 } 360 361 362 void 363 interact(lp, fd) 364 struct disklabel *lp; 365 int fd; 366 { 367 char line[BUFSIZ]; 368 369 for (;;) { 370 if (getinput(">", "partition", NULL, line) == -1) 371 return; 372 if (runcmd(line, lp, fd) == -1) 373 return; 374 } 375 } 376