1 /* $OpenBSD: io.c,v 1.31 2016/02/01 18:55:00 krw Exp $ */ 2 3 /* 4 * io.c - simple io and input parsing routines 5 * 6 * Written by Eryk Vershen 7 */ 8 9 /* 10 * Copyright 1996,1997,1998 by Apple Computer, Inc. 11 * All Rights Reserved 12 * 13 * Permission to use, copy, modify, and distribute this software and 14 * its documentation for any purpose and without fee is hereby granted, 15 * provided that the above copyright notice appears in all copies and 16 * that both the copyright notice and this permission notice appear in 17 * supporting documentation. 18 * 19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE. 22 * 23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 #include <sys/queue.h> 31 32 #include <err.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <stdarg.h> 37 38 #include "partition_map.h" 39 #include "io.h" 40 41 #define UNGET_MAX_COUNT 10 42 43 short unget_buf[UNGET_MAX_COUNT + 1]; 44 int unget_count; 45 46 static int get_number(long *); 47 static char *get_string(int); 48 static int my_getch (void); 49 50 int 51 my_getch() 52 { 53 if (unget_count > 0) 54 return unget_buf[--unget_count]; 55 else 56 return getc(stdin); 57 } 58 59 60 void 61 my_ungetch(int c) 62 { 63 /* 64 * In practice there is never more than one character in 65 * the unget_buf, but what's a little overkill among friends? 66 */ 67 if (unget_count < UNGET_MAX_COUNT) 68 unget_buf[unget_count++] = c; 69 else 70 errx(1, "Programmer error in my_ungetch()."); 71 } 72 73 void 74 flush_to_newline(int keep_newline) 75 { 76 int c; 77 78 for (;;) { 79 c = my_getch(); 80 81 if (c <= 0) { 82 break; 83 } else if (c == '\n') { 84 if (keep_newline) 85 my_ungetch(c); 86 break; 87 } else { 88 /* skip */ 89 } 90 } 91 return; 92 } 93 94 95 int 96 get_okay(const char *prompt, int default_value) 97 { 98 int c; 99 100 flush_to_newline(0); 101 printf("%s", prompt); 102 103 for (;;) { 104 c = my_getch(); 105 106 if (c <= 0) { 107 break; 108 } else if (c == ' ' || c == '\t') { 109 /* skip blanks and tabs */ 110 } else if (c == '\n') { 111 my_ungetch(c); 112 return default_value; 113 } else if (c == 'y' || c == 'Y') { 114 return 1; 115 } else if (c == 'n' || c == 'N') { 116 return 0; 117 } else { 118 flush_to_newline(0); 119 printf("%s", prompt); 120 } 121 } 122 return -1; 123 } 124 125 int 126 get_command(const char *prompt, int promptBeforeGet, int *command) 127 { 128 int c; 129 130 if (promptBeforeGet) 131 printf("%s", prompt); 132 133 for (;;) { 134 c = my_getch(); 135 136 if (c <= 0) { 137 break; 138 } else if (c == ' ' || c == '\t') { 139 /* skip blanks and tabs */ 140 } else if (c == '\n') { 141 printf("%s", prompt); 142 } else { 143 *command = c; 144 return 1; 145 } 146 } 147 return 0; 148 } 149 150 int 151 get_number_argument(const char *prompt, long *number) 152 { 153 int c; 154 int result = 0; 155 156 for (;;) { 157 c = my_getch(); 158 159 if (c <= 0) { 160 break; 161 } else if (c == ' ' || c == '\t') { 162 /* skip blanks and tabs */ 163 } else if (c == '\n') { 164 printf("%s", prompt); 165 } else if ('0' <= c && c <= '9') { 166 my_ungetch(c); 167 result = get_number(number); 168 break; 169 } else { 170 my_ungetch(c); 171 *number = 0; 172 break; 173 } 174 } 175 return result; 176 } 177 178 179 int 180 get_number(long *number) 181 { 182 long value; 183 int c; 184 185 value = 0; 186 while ((c = my_getch())) { 187 if (c >= '0' && c <= '9') { 188 value = value * 10 + (c - '0'); 189 } else if (c == ' ' || c == '\t' || c == '\n') { 190 my_ungetch(c); 191 *number = value; 192 return 1; 193 } else { 194 return 0; 195 } 196 } 197 198 return 0; 199 } 200 201 char * 202 get_dpistr_argument(const char *prompt) 203 { 204 int c; 205 206 for (;;) { 207 c = my_getch(); 208 209 if (c <= 0) { 210 break; 211 } else if (c == ' ' || c == '\t') { 212 /* skip blanks and tabs */ 213 } else if (c == '\n') { 214 printf("%s", prompt); 215 } else if (c == '"' || c == '\'') { 216 return get_string(c); 217 } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 218 (c == '-' || c == '/' || c == '.' || c == ':')) { 219 my_ungetch(c); 220 return get_string(' '); 221 } else { 222 my_ungetch(c); 223 return NULL; 224 } 225 } 226 return NULL; 227 } 228 229 230 char * 231 get_string(int eos) 232 { 233 char buf[DPISTRLEN+1]; 234 char *s, *limit; 235 int c; 236 237 memset(buf, 0, sizeof(buf)); 238 limit = buf + sizeof(buf); 239 240 c = my_getch(); 241 for (s = buf;; c = my_getch()) { 242 if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) { 243 *s = 0; 244 break; 245 } else if (c == '\n') { 246 *s = 0; 247 my_ungetch(c); 248 break; 249 } else { 250 *s++ = c; 251 if (s >= limit) 252 return NULL; 253 } 254 } 255 return strdup(buf); 256 } 257 258 259 unsigned long 260 get_multiplier(long divisor) 261 { 262 unsigned long result, extra; 263 int c; 264 265 c = my_getch(); 266 267 extra = 1; 268 if (c <= 0 || divisor <= 0) { 269 result = 0; 270 } else if (c == 't' || c == 'T') { 271 result = 1024 * 1024; 272 extra = 1024 * 1024; 273 } else if (c == 'g' || c == 'G') { 274 result = 1024 * 1024 * 1024; 275 } else if (c == 'm' || c == 'M') { 276 result = 1024 * 1024; 277 } else if (c == 'k' || c == 'K') { 278 result = 1024; 279 } else { 280 my_ungetch(c); 281 result = 1; 282 } 283 if (result > 1) { 284 if (extra > 1) { 285 result /= divisor; 286 if (result >= 4096) 287 result = 0; /* overflow -> 20bits + >12bits */ 288 else 289 result *= extra; 290 } else if (result >= divisor) { 291 result /= divisor; 292 } else { 293 result = 1; 294 } 295 } 296 return result; 297 } 298 299 300 int 301 get_partition_modifier(void) 302 { 303 int c, result; 304 305 result = 0; 306 307 c = my_getch(); 308 309 if (c == 'p' || c == 'P') 310 result = 1; 311 else if (c > 0) 312 my_ungetch(c); 313 314 return result; 315 } 316 317 318 int 319 number_of_digits(unsigned long value) 320 { 321 int j; 322 323 j = 1; 324 while (value > 9) { 325 j++; 326 value = value / 10; 327 } 328 return j; 329 } 330 331 332 /* 333 * Print a message on standard error & flush the input. 334 */ 335 void 336 bad_input(const char *fmt,...) 337 { 338 va_list ap; 339 340 va_start(ap, fmt); 341 vfprintf(stderr, fmt, ap); 342 va_end(ap); 343 fprintf(stderr, "\n"); 344 flush_to_newline(1); 345 } 346