1 /* $OpenBSD: misc.c,v 1.42 2014/03/31 19:50:52 krw Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/types.h> 29 #include <sys/disklabel.h> 30 #include <ctype.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <err.h> 35 #include <errno.h> 36 37 #include "disk.h" 38 #include "misc.h" 39 #include "part.h" 40 41 struct unit_type unit_types[] = { 42 {"b", 1 , "Bytes"}, 43 {" ", 0 , "Sectors"}, /* Filled in from disklabel. */ 44 {"K", 1024 , "Kilobytes"}, 45 {"M", 1024 * 1024 , "Megabytes"}, 46 {"G", 1024 * 1024 *1024 , "Gigabytes"}, 47 {NULL, 0 , NULL }, 48 }; 49 50 int 51 unit_lookup(char *units) 52 { 53 int i = 0; 54 if (units == NULL) 55 return (SECTORS); 56 57 while (unit_types[i].abbr != NULL) { 58 if (strncasecmp(unit_types[i].abbr, units, 1) == 0) 59 break; 60 i++; 61 } 62 /* default */ 63 if (unit_types[i].abbr == NULL) 64 return (SECTORS); 65 66 return (i); 67 } 68 69 int 70 ask_cmd(char **cmd, char **args) 71 { 72 static char lbuf[100]; 73 char *cp, *buf; 74 size_t lbuflen; 75 76 /* Get input */ 77 if (fgets(lbuf, sizeof lbuf, stdin) == NULL) 78 errx(1, "eof"); 79 lbuflen = strlen(lbuf); 80 if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') 81 lbuf[lbuflen - 1] = '\0'; 82 83 /* Parse input */ 84 buf = lbuf; 85 buf = &buf[strspn(buf, " \t")]; 86 cp = &buf[strcspn(buf, " \t")]; 87 *cp++ = '\0'; 88 *cmd = buf; 89 *args = &cp[strspn(cp, " \t")]; 90 91 return (0); 92 } 93 94 int 95 ask_num(const char *str, int dflt, int low, int high) 96 { 97 char lbuf[100]; 98 const char *errstr; 99 size_t lbuflen; 100 int num; 101 102 if (dflt < low) 103 dflt = low; 104 else if (dflt > high) 105 dflt = high; 106 107 do { 108 printf("%s [%d - %d]: [%d] ", str, low, high, dflt); 109 110 if (fgets(lbuf, sizeof lbuf, stdin) == NULL) 111 errx(1, "eof"); 112 113 lbuflen = strlen(lbuf); 114 if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') 115 lbuf[lbuflen - 1] = '\0'; 116 117 if (lbuf[0] == '\0') { 118 num = dflt; 119 errstr = NULL; 120 } else { 121 num = (int)strtonum(lbuf, low, high, &errstr); 122 if (errstr) 123 printf("%s is %s: %s.\n", str, errstr, lbuf); 124 } 125 } while (errstr); 126 127 return (num); 128 } 129 130 int 131 ask_pid(int dflt) 132 { 133 char lbuf[100], *cp; 134 size_t lbuflen; 135 int num = -1; 136 const int low = 0, high = 0xff; 137 138 if (dflt < low) 139 dflt = low; 140 else if (dflt > high) 141 dflt = high; 142 143 do { 144 printf("Partition id ('0' to disable) [%X - %X]: [%X] ", low, 145 high, dflt); 146 printf("(? for help) "); 147 148 if (fgets(lbuf, sizeof lbuf, stdin) == NULL) 149 errx(1, "eof"); 150 lbuflen = strlen(lbuf); 151 if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') 152 lbuf[lbuflen - 1] = '\0'; 153 154 if (lbuf[0] == '?') { 155 PRT_printall(); 156 continue; 157 } 158 159 /* Convert */ 160 cp = lbuf; 161 num = strtol(lbuf, &cp, 16); 162 163 /* Make sure only number present */ 164 if (cp == lbuf) 165 num = dflt; 166 if (*cp != '\0') { 167 printf("'%s' is not a valid number.\n", lbuf); 168 num = low - 1; 169 } else if (num < low || num > high) { 170 printf("'%x' is out of range.\n", num); 171 } 172 } while (num < low || num > high); 173 174 return (num); 175 } 176 177 int 178 ask_yn(const char *str) 179 { 180 int ch, first; 181 extern int y_flag; 182 183 if (y_flag) 184 return (1); 185 186 printf("%s [n] ", str); 187 fflush(stdout); 188 189 first = ch = getchar(); 190 while (ch != '\n' && ch != EOF) 191 ch = getchar(); 192 193 if (ch == EOF || first == EOF) 194 errx(1, "eof"); 195 196 return (first == 'y' || first == 'Y'); 197 } 198 199 /* 200 * adapted from sbin/disklabel/editor.c 201 */ 202 u_int32_t 203 getuint(struct disk *disk, char *prompt, u_int32_t oval, u_int32_t maxval) 204 { 205 char buf[BUFSIZ], *endptr, *p, operator = '\0'; 206 size_t n; 207 int mult = 1, secsize = unit_types[SECTORS].conversion; 208 double d, d2; 209 int secpercyl, saveerr; 210 char unit; 211 212 if (oval > maxval) 213 oval = maxval; 214 215 secpercyl = disk->sectors * disk->heads; 216 217 do { 218 printf("%s: [%u] ", prompt, oval); 219 220 if (fgets(buf, sizeof(buf), stdin) == NULL) 221 errx(1, "eof"); 222 223 n = strlen(buf); 224 if (n > 0 && buf[n-1] == '\n') 225 buf[--n] = '\0'; 226 227 if (buf[0] == '\0') { 228 return (oval); 229 } else if (buf[0] == '*' && buf[1] == '\0') { 230 return (maxval); 231 } 232 233 /* deal with units */ 234 switch (tolower((unsigned char)buf[n-1])) { 235 case 'c': 236 unit = 'c'; 237 mult = secpercyl; 238 buf[--n] = '\0'; 239 break; 240 case 'b': 241 unit = 'b'; 242 mult = -secsize; 243 buf[--n] = '\0'; 244 break; 245 case 's': 246 unit = 's'; 247 mult = 1; 248 buf[--n] = '\0'; 249 break; 250 case 'k': 251 unit = 'k'; 252 if (secsize > 1024) 253 mult = -secsize / 1024; 254 else 255 mult = 1024 / secsize; 256 buf[--n] = '\0'; 257 break; 258 case 'm': 259 unit = 'm'; 260 mult = 1048576 / secsize; 261 buf[--n] = '\0'; 262 break; 263 case 'g': 264 unit = 'g'; 265 mult = 1073741824 / secsize; 266 buf[--n] = '\0'; 267 break; 268 default: 269 unit = ' '; 270 mult = 1; 271 break; 272 } 273 274 /* deal with the operator */ 275 p = &buf[0]; 276 if (*p == '+' || *p == '-') 277 operator = *p++; 278 else 279 operator = ' '; 280 281 endptr = p; 282 errno = 0; 283 d = strtod(p, &endptr); 284 saveerr = errno; 285 d2 = d; 286 if (mult > 0) 287 d *= mult; 288 else { 289 d /= (-mult); 290 d2 = d; 291 } 292 293 /* Apply the operator */ 294 if (operator == '+') 295 d = oval + d; 296 else if (operator == '-') { 297 d = oval - d; 298 d2 = d; 299 } 300 301 if (saveerr == ERANGE || d > maxval || d < 0 || d < d2) { 302 printf("%s is out of range: %c%s%c\n", prompt, operator, 303 p, unit); 304 } else if (*endptr != '\0') { 305 printf("%s is invalid: %c%s%c\n", prompt, operator, 306 p, unit); 307 } else { 308 break; 309 } 310 } while (1); 311 312 return ((u_int32_t)d); 313 } 314