1 /* $OpenBSD: io.c,v 1.29 2016/01/29 18:40:08 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 <err.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <stdarg.h> 35 36 #include "dpme.h" 37 #include "io.h" 38 39 #define UNGET_MAX_COUNT 10 40 41 short unget_buf[UNGET_MAX_COUNT + 1]; 42 int unget_count; 43 44 static int get_number(long *); 45 static char *get_string(int); 46 static int my_getch (void); 47 48 int 49 my_getch() 50 { 51 if (unget_count > 0) 52 return unget_buf[--unget_count]; 53 else 54 return getc(stdin); 55 } 56 57 58 void 59 my_ungetch(int c) 60 { 61 /* 62 * In practice there is never more than one character in 63 * the unget_buf, but what's a little overkill among friends? 64 */ 65 if (unget_count < UNGET_MAX_COUNT) 66 unget_buf[unget_count++] = c; 67 else 68 errx(1, "Programmer error in my_ungetch()."); 69 } 70 71 void 72 flush_to_newline(int keep_newline) 73 { 74 int c; 75 76 for (;;) { 77 c = my_getch(); 78 79 if (c <= 0) { 80 break; 81 } else if (c == '\n') { 82 if (keep_newline) 83 my_ungetch(c); 84 break; 85 } else { 86 /* skip */ 87 } 88 } 89 return; 90 } 91 92 93 int 94 get_okay(const char *prompt, int default_value) 95 { 96 int c; 97 98 flush_to_newline(0); 99 printf(prompt); 100 101 for (;;) { 102 c = my_getch(); 103 104 if (c <= 0) { 105 break; 106 } else if (c == ' ' || c == '\t') { 107 /* skip blanks and tabs */ 108 } else if (c == '\n') { 109 my_ungetch(c); 110 return default_value; 111 } else if (c == 'y' || c == 'Y') { 112 return 1; 113 } else if (c == 'n' || c == 'N') { 114 return 0; 115 } else { 116 flush_to_newline(0); 117 printf(prompt); 118 } 119 } 120 return -1; 121 } 122 123 int 124 get_command(const char *prompt, int promptBeforeGet, int *command) 125 { 126 int c; 127 128 if (promptBeforeGet) 129 printf(prompt); 130 131 for (;;) { 132 c = my_getch(); 133 134 if (c <= 0) { 135 break; 136 } else if (c == ' ' || c == '\t') { 137 /* skip blanks and tabs */ 138 } else if (c == '\n') { 139 printf(prompt); 140 } else { 141 *command = c; 142 return 1; 143 } 144 } 145 return 0; 146 } 147 148 int 149 get_number_argument(const char *prompt, long *number) 150 { 151 int c; 152 int result = 0; 153 154 for (;;) { 155 c = my_getch(); 156 157 if (c <= 0) { 158 break; 159 } else if (c == ' ' || c == '\t') { 160 /* skip blanks and tabs */ 161 } else if (c == '\n') { 162 printf(prompt); 163 } else if ('0' <= c && c <= '9') { 164 my_ungetch(c); 165 result = get_number(number); 166 break; 167 } else { 168 my_ungetch(c); 169 *number = 0; 170 break; 171 } 172 } 173 return result; 174 } 175 176 177 int 178 get_number(long *number) 179 { 180 long value; 181 int c; 182 183 value = 0; 184 while ((c = my_getch())) { 185 if (c >= '0' && c <= '9') { 186 value = value * 10 + (c - '0'); 187 } else if (c == ' ' || c == '\t' || c == '\n') { 188 my_ungetch(c); 189 *number = value; 190 return 1; 191 } else { 192 return 0; 193 } 194 } 195 196 return 0; 197 } 198 199 char * 200 get_dpistr_argument(const char *prompt) 201 { 202 int c; 203 204 for (;;) { 205 c = my_getch(); 206 207 if (c <= 0) { 208 break; 209 } else if (c == ' ' || c == '\t') { 210 /* skip blanks and tabs */ 211 } else if (c == '\n') { 212 printf(prompt); 213 } else if (c == '"' || c == '\'') { 214 return get_string(c); 215 } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 216 (c == '-' || c == '/' || c == '.' || c == ':')) { 217 my_ungetch(c); 218 return get_string(' '); 219 } else { 220 my_ungetch(c); 221 return NULL; 222 } 223 } 224 return NULL; 225 } 226 227 228 char * 229 get_string(int eos) 230 { 231 char buf[DPISTRLEN+1]; 232 char *s, *limit; 233 int c; 234 235 memset(buf, 0, sizeof(buf)); 236 limit = buf + sizeof(buf); 237 238 c = my_getch(); 239 for (s = buf;; c = my_getch()) { 240 if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) { 241 *s = 0; 242 break; 243 } else if (c == '\n') { 244 *s = 0; 245 my_ungetch(c); 246 break; 247 } else { 248 *s++ = c; 249 if (s >= limit) 250 return NULL; 251 } 252 } 253 return strdup(buf); 254 } 255 256 257 unsigned long 258 get_multiplier(long divisor) 259 { 260 unsigned long result, extra; 261 int c; 262 263 c = my_getch(); 264 265 extra = 1; 266 if (c <= 0 || divisor <= 0) { 267 result = 0; 268 } else if (c == 't' || c == 'T') { 269 result = 1024 * 1024; 270 extra = 1024 * 1024; 271 } else if (c == 'g' || c == 'G') { 272 result = 1024 * 1024 * 1024; 273 } else if (c == 'm' || c == 'M') { 274 result = 1024 * 1024; 275 } else if (c == 'k' || c == 'K') { 276 result = 1024; 277 } else { 278 my_ungetch(c); 279 result = 1; 280 } 281 if (result > 1) { 282 if (extra > 1) { 283 result /= divisor; 284 if (result >= 4096) 285 result = 0; /* overflow -> 20bits + >12bits */ 286 else 287 result *= extra; 288 } else if (result >= divisor) { 289 result /= divisor; 290 } else { 291 result = 1; 292 } 293 } 294 return result; 295 } 296 297 298 int 299 get_partition_modifier(void) 300 { 301 int c, result; 302 303 result = 0; 304 305 c = my_getch(); 306 307 if (c == 'p' || c == 'P') 308 result = 1; 309 else if (c > 0) 310 my_ungetch(c); 311 312 return result; 313 } 314 315 316 int 317 number_of_digits(unsigned long value) 318 { 319 int j; 320 321 j = 1; 322 while (value > 9) { 323 j++; 324 value = value / 10; 325 } 326 return j; 327 } 328 329 330 /* 331 * Print a message on standard error & flush the input. 332 */ 333 void 334 bad_input(const char *fmt,...) 335 { 336 va_list ap; 337 338 va_start(ap, fmt); 339 vfprintf(stderr, fmt, ap); 340 va_end(ap); 341 fprintf(stderr, "\n"); 342 flush_to_newline(1); 343 } 344