1 /* $OpenBSD: misc.c,v 1.29 2012/07/11 10:27:34 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 <err.h> 29 #include <stdio.h> 30 #include <ctype.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <errno.h> 34 #include <sys/disklabel.h> 35 #include <limits.h> 36 #include "misc.h" 37 38 struct unit_type unit_types[] = { 39 {"b", 1 , "Bytes"}, 40 {" ", DEV_BSIZE , "Sectors"}, 41 {"K", 1024 , "Kilobytes"}, 42 {"M", 1024 * 1024 , "Megabytes"}, 43 {"G", 1024 * 1024 *1024 , "Gigabytes"}, 44 {NULL, 0 , NULL }, 45 }; 46 47 int 48 unit_lookup(char *units) 49 { 50 int i = 0; 51 if (units == NULL) 52 return (UNIT_TYPE_DEFAULT); 53 54 while (unit_types[i].abbr != NULL) { 55 if (strncasecmp(unit_types[i].abbr, units, 1) == 0) 56 break; 57 i++; 58 } 59 /* default */ 60 if (unit_types[i].abbr == NULL) 61 return (UNIT_TYPE_DEFAULT); 62 63 return (i); 64 } 65 66 int 67 ask_cmd(cmd_t *cmd) 68 { 69 char lbuf[100], *cp, *buf; 70 size_t lbuflen; 71 72 /* Get input */ 73 if (fgets(lbuf, sizeof lbuf, stdin) == NULL) 74 errx(1, "eof"); 75 lbuflen = strlen(lbuf); 76 if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') 77 lbuf[lbuflen - 1] = '\0'; 78 79 /* Parse input */ 80 buf = lbuf; 81 buf = &buf[strspn(buf, " \t")]; 82 cp = &buf[strcspn(buf, " \t")]; 83 *cp++ = '\0'; 84 strncpy(cmd->cmd, buf, sizeof(cmd->cmd)); 85 buf = &cp[strspn(cp, " \t")]; 86 strncpy(cmd->args, buf, sizeof(cmd->args)); 87 88 return (0); 89 } 90 91 int 92 ask_num(const char *str, int dflt, int low, int high) 93 { 94 char lbuf[100], *cp; 95 const char *errstr; 96 size_t lbuflen; 97 int num; 98 99 if (dflt < low) 100 dflt = low; 101 else if (dflt > high) 102 dflt = high; 103 104 do { 105 printf("%s [%d - %d]: [%d] ", str, low, high, dflt); 106 107 if (fgets(lbuf, sizeof lbuf, stdin) == NULL) 108 errx(1, "eof"); 109 110 lbuflen = strlen(lbuf); 111 if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') 112 lbuf[lbuflen - 1] = '\0'; 113 114 if (lbuf[0] == '\0') { 115 num = dflt; 116 errstr = NULL; 117 } else { 118 num = (int)strtonum(lbuf, low, high, &errstr); 119 if (errstr) 120 printf("%s is %s: %s.\n", str, errstr, lbuf); 121 } 122 } while (errstr); 123 124 return (num); 125 } 126 127 int 128 ask_pid(int dflt) 129 { 130 char lbuf[100], *cp; 131 size_t lbuflen; 132 int num; 133 const int low = 0, high = 0xff; 134 135 if (dflt < low) 136 dflt = low; 137 else if (dflt > high) 138 dflt = high; 139 140 do { 141 again: 142 printf("Partition id ('0' to disable) [%X - %X]: [%X] ", low, 143 high, dflt); 144 printf("(? for help) "); 145 146 if (fgets(lbuf, sizeof lbuf, stdin) == NULL) 147 errx(1, "eof"); 148 lbuflen = strlen(lbuf); 149 if (lbuflen > 0 && lbuf[lbuflen - 1] == '\n') 150 lbuf[lbuflen - 1] = '\0'; 151 152 if (lbuf[0] == '?') { 153 PRT_printall(); 154 goto again; 155 } 156 157 /* Convert */ 158 cp = lbuf; 159 num = strtol(lbuf, &cp, 16); 160 161 /* Make sure only number present */ 162 if (cp == lbuf) 163 num = dflt; 164 if (*cp != '\0') { 165 printf("'%s' is not a valid number.\n", lbuf); 166 num = low - 1; 167 } else if (num < low || num > high) { 168 printf("'%x' is out of range.\n", num); 169 } 170 } while (num < low || num > high); 171 172 return (num); 173 } 174 175 int 176 ask_yn(const char *str) 177 { 178 int ch, first; 179 extern int y_flag; 180 181 if (y_flag) 182 return (1); 183 184 printf("%s [n] ", str); 185 fflush(stdout); 186 187 first = ch = getchar(); 188 while (ch != '\n' && ch != EOF) 189 ch = getchar(); 190 191 if (ch == EOF || first == EOF) 192 errx(1, "eof"); 193 194 return (first == 'y' || first == 'Y'); 195 } 196 197 u_int16_t 198 getshort(void *p) 199 { 200 unsigned char *cp = p; 201 202 return (cp[0] | (cp[1] << 8)); 203 } 204 205 void 206 putshort(void *p, u_int16_t l) 207 { 208 unsigned char *cp = p; 209 210 *cp++ = l; 211 *cp++ = l >> 8; 212 } 213 214 u_int32_t 215 getlong(void *p) 216 { 217 unsigned char *cp = p; 218 219 return (cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24)); 220 } 221 222 void 223 putlong(void *p, u_int32_t l) 224 { 225 unsigned char *cp = p; 226 227 *cp++ = l; 228 *cp++ = l >> 8; 229 *cp++ = l >> 16; 230 *cp++ = l >> 24; 231 } 232 233 /* 234 * adapted from sbin/disklabel/editor.c 235 */ 236 u_int32_t 237 getuint(disk_t *disk, char *prompt, u_int32_t oval, u_int32_t maxval) 238 { 239 char buf[BUFSIZ], *endptr, *p, operator = '\0'; 240 size_t n; 241 int mult = 1, secsize = unit_types[SECTORS].conversion; 242 double d, d2; 243 int secpercyl, saveerr; 244 char unit; 245 246 if (oval > maxval) 247 oval = maxval; 248 249 secpercyl = disk->real->sectors * disk->real->heads; 250 251 do { 252 printf("%s: [%u] ", prompt, oval); 253 254 if (fgets(buf, sizeof(buf), stdin) == NULL) 255 errx(1, "eof"); 256 257 n = strlen(buf); 258 if (n > 0 && buf[n-1] == '\n') 259 buf[--n] = '\0'; 260 261 if (buf[0] == '\0') { 262 return (oval); 263 } else if (buf[0] == '*' && buf[1] == '\0') { 264 return (maxval); 265 } 266 267 /* deal with units */ 268 switch (tolower(buf[n-1])) { 269 case 'c': 270 unit = 'c'; 271 mult = secpercyl; 272 buf[--n] = '\0'; 273 break; 274 case 'b': 275 unit = 'b'; 276 mult = -secsize; 277 buf[--n] = '\0'; 278 break; 279 case 's': 280 unit = 's'; 281 mult = 1; 282 buf[--n] = '\0'; 283 break; 284 case 'k': 285 unit = 'k'; 286 if (secsize > 1024) 287 mult = -secsize / 1024; 288 else 289 mult = 1024 / secsize; 290 buf[--n] = '\0'; 291 break; 292 case 'm': 293 unit = 'm'; 294 mult = 1048576 / secsize; 295 buf[--n] = '\0'; 296 break; 297 case 'g': 298 unit = 'g'; 299 mult = 1073741824 / secsize; 300 buf[--n] = '\0'; 301 break; 302 default: 303 unit = ' '; 304 mult = 1; 305 break; 306 } 307 308 /* deal with the operator */ 309 p = &buf[0]; 310 if (*p == '+' || *p == '-') 311 operator = *p++; 312 else 313 operator = ' '; 314 315 endptr = p; 316 errno = 0; 317 d = strtod(p, &endptr); 318 saveerr = errno; 319 d2 = d; 320 if (mult > 0) 321 d *= mult; 322 else { 323 d /= (-mult); 324 d2 = d; 325 } 326 327 /* Apply the operator */ 328 if (operator == '+') 329 d = oval + d; 330 else if (operator == '-') { 331 d = oval - d; 332 d2 = d; 333 } 334 335 if (saveerr == ERANGE || d > maxval || d < 0 || d < d2) { 336 printf("%s is out of range: %c%s%c\n", prompt, operator, 337 p, unit); 338 } else if (*endptr != '\0') { 339 printf("%s is invalid: %c%s%c\n", prompt, operator, 340 p, unit); 341 } else { 342 break; 343 } 344 } while (1); 345 346 return ((u_int32_t)d); 347 } 348