io.c revision 1.30
1251876Speter/* $OpenBSD: io.c,v 1.30 2016/01/30 17:21:10 krw Exp $ */ 2251876Speter 3251876Speter/* 4251876Speter * io.c - simple io and input parsing routines 5251876Speter * 6251876Speter * Written by Eryk Vershen 7251876Speter */ 8251876Speter 9251876Speter/* 10251876Speter * Copyright 1996,1997,1998 by Apple Computer, Inc. 11251876Speter * All Rights Reserved 12251876Speter * 13251876Speter * Permission to use, copy, modify, and distribute this software and 14251876Speter * its documentation for any purpose and without fee is hereby granted, 15251876Speter * provided that the above copyright notice appears in all copies and 16251876Speter * that both the copyright notice and this permission notice appear in 17251876Speter * supporting documentation. 18251876Speter * 19251876Speter * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 20251876Speter * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21251876Speter * FOR A PARTICULAR PURPOSE. 22251876Speter * 23251876Speter * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 24251876Speter * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 25251876Speter * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 26251876Speter * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 27251876Speter * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 28251876Speter */ 29251876Speter 30251876Speter#include <sys/queue.h> 31251876Speter 32251876Speter#include <err.h> 33251876Speter#include <stdio.h> 34251876Speter#include <stdlib.h> 35251876Speter#include <string.h> 36251876Speter#include <stdarg.h> 37251876Speter 38251876Speter#include "partition_map.h" 39251876Speter#include "io.h" 40251876Speter 41251876Speter#define UNGET_MAX_COUNT 10 42251876Speter 43251876Spetershort unget_buf[UNGET_MAX_COUNT + 1]; 44251876Speterint unget_count; 45251876Speter 46251876Speterstatic int get_number(long *); 47251876Speterstatic char *get_string(int); 48251876Speterstatic int my_getch (void); 49251876Speter 50251876Speterint 51251876Spetermy_getch() 52251876Speter{ 53251876Speter if (unget_count > 0) 54251876Speter return unget_buf[--unget_count]; 55251876Speter else 56251876Speter return getc(stdin); 57251876Speter} 58251876Speter 59251876Speter 60251876Spetervoid 61251876Spetermy_ungetch(int c) 62251876Speter{ 63251876Speter /* 64251876Speter * In practice there is never more than one character in 65251876Speter * the unget_buf, but what's a little overkill among friends? 66251876Speter */ 67251876Speter if (unget_count < UNGET_MAX_COUNT) 68251876Speter unget_buf[unget_count++] = c; 69251876Speter else 70251876Speter errx(1, "Programmer error in my_ungetch()."); 71251876Speter} 72251876Speter 73251876Spetervoid 74251876Speterflush_to_newline(int keep_newline) 75251876Speter{ 76251876Speter int c; 77251876Speter 78251876Speter for (;;) { 79251876Speter c = my_getch(); 80251876Speter 81251876Speter if (c <= 0) { 82251876Speter break; 83251876Speter } else if (c == '\n') { 84251876Speter if (keep_newline) 85251876Speter my_ungetch(c); 86251876Speter break; 87251876Speter } else { 88251876Speter /* skip */ 89251876Speter } 90251876Speter } 91251876Speter return; 92251876Speter} 93251876Speter 94251876Speter 95251876Speterint 96251876Speterget_okay(const char *prompt, int default_value) 97251876Speter{ 98251876Speter int c; 99251876Speter 100251876Speter flush_to_newline(0); 101251876Speter printf(prompt); 102251876Speter 103251876Speter for (;;) { 104251876Speter c = my_getch(); 105251876Speter 106251876Speter if (c <= 0) { 107251876Speter break; 108251876Speter } else if (c == ' ' || c == '\t') { 109251876Speter /* skip blanks and tabs */ 110251876Speter } else if (c == '\n') { 111251876Speter my_ungetch(c); 112251876Speter return default_value; 113251876Speter } else if (c == 'y' || c == 'Y') { 114251876Speter return 1; 115251876Speter } else if (c == 'n' || c == 'N') { 116251876Speter return 0; 117251876Speter } else { 118251876Speter flush_to_newline(0); 119251876Speter printf(prompt); 120251876Speter } 121251876Speter } 122251876Speter return -1; 123251876Speter} 124251876Speter 125251876Speterint 126251876Speterget_command(const char *prompt, int promptBeforeGet, int *command) 127251876Speter{ 128251876Speter int c; 129251876Speter 130251876Speter if (promptBeforeGet) 131251876Speter printf(prompt); 132251876Speter 133251876Speter for (;;) { 134251876Speter c = my_getch(); 135251876Speter 136251876Speter if (c <= 0) { 137251876Speter break; 138251876Speter } else if (c == ' ' || c == '\t') { 139251876Speter /* skip blanks and tabs */ 140251876Speter } else if (c == '\n') { 141251876Speter printf(prompt); 142251876Speter } else { 143251876Speter *command = c; 144251876Speter return 1; 145251876Speter } 146251876Speter } 147251876Speter return 0; 148251876Speter} 149251876Speter 150251876Speterint 151251876Speterget_number_argument(const char *prompt, long *number) 152251876Speter{ 153251876Speter int c; 154251876Speter int result = 0; 155251876Speter 156251876Speter for (;;) { 157251876Speter c = my_getch(); 158251876Speter 159251876Speter if (c <= 0) { 160251876Speter break; 161251876Speter } else if (c == ' ' || c == '\t') { 162251876Speter /* skip blanks and tabs */ 163251876Speter } else if (c == '\n') { 164251876Speter printf(prompt); 165251876Speter } else if ('0' <= c && c <= '9') { 166251876Speter my_ungetch(c); 167251876Speter result = get_number(number); 168251876Speter break; 169251876Speter } else { 170251876Speter my_ungetch(c); 171251876Speter *number = 0; 172251876Speter break; 173251876Speter } 174251876Speter } 175251876Speter return result; 176251876Speter} 177251876Speter 178251876Speter 179251876Speterint 180251876Speterget_number(long *number) 181251876Speter{ 182251876Speter long value; 183251876Speter int c; 184251876Speter 185251876Speter value = 0; 186251876Speter while ((c = my_getch())) { 187251876Speter if (c >= '0' && c <= '9') { 188251876Speter value = value * 10 + (c - '0'); 189251876Speter } else if (c == ' ' || c == '\t' || c == '\n') { 190251876Speter my_ungetch(c); 191251876Speter *number = value; 192251876Speter return 1; 193251876Speter } else { 194251876Speter return 0; 195251876Speter } 196251876Speter } 197251876Speter 198251876Speter return 0; 199251876Speter} 200251876Speter 201251876Speterchar * 202251876Speterget_dpistr_argument(const char *prompt) 203251876Speter{ 204251876Speter int c; 205251876Speter 206251876Speter for (;;) { 207251876Speter c = my_getch(); 208251876Speter 209251876Speter if (c <= 0) { 210251876Speter break; 211251876Speter } else if (c == ' ' || c == '\t') { 212251876Speter /* skip blanks and tabs */ 213251876Speter } else if (c == '\n') { 214251876Speter printf(prompt); 215251876Speter } else if (c == '"' || c == '\'') { 216251876Speter return get_string(c); 217251876Speter } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 218251876Speter (c == '-' || c == '/' || c == '.' || c == ':')) { 219251876Speter my_ungetch(c); 220251876Speter return get_string(' '); 221251876Speter } else { 222251876Speter my_ungetch(c); 223251876Speter return NULL; 224251876Speter } 225251876Speter } 226251876Speter return NULL; 227251876Speter} 228251876Speter 229251876Speter 230251876Speterchar * 231251876Speterget_string(int eos) 232251876Speter{ 233251876Speter char buf[DPISTRLEN+1]; 234251876Speter char *s, *limit; 235251876Speter int c; 236251876Speter 237251876Speter memset(buf, 0, sizeof(buf)); 238251876Speter limit = buf + sizeof(buf); 239251876Speter 240251876Speter c = my_getch(); 241251876Speter for (s = buf;; c = my_getch()) { 242251876Speter if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) { 243251876Speter *s = 0; 244251876Speter break; 245251876Speter } else if (c == '\n') { 246251876Speter *s = 0; 247251876Speter my_ungetch(c); 248251876Speter break; 249251876Speter } else { 250251876Speter *s++ = c; 251251876Speter if (s >= limit) 252251876Speter return NULL; 253251876Speter } 254251876Speter } 255251876Speter return strdup(buf); 256251876Speter} 257251876Speter 258251876Speter 259251876Speterunsigned long 260251876Speterget_multiplier(long divisor) 261251876Speter{ 262251876Speter unsigned long result, extra; 263251876Speter int c; 264251876Speter 265251876Speter c = my_getch(); 266251876Speter 267251876Speter extra = 1; 268251876Speter if (c <= 0 || divisor <= 0) { 269251876Speter result = 0; 270251876Speter } else if (c == 't' || c == 'T') { 271251876Speter result = 1024 * 1024; 272251876Speter extra = 1024 * 1024; 273251876Speter } else if (c == 'g' || c == 'G') { 274251876Speter result = 1024 * 1024 * 1024; 275251876Speter } else if (c == 'm' || c == 'M') { 276251876Speter result = 1024 * 1024; 277251876Speter } else if (c == 'k' || c == 'K') { 278251876Speter result = 1024; 279251876Speter } else { 280251876Speter my_ungetch(c); 281251876Speter result = 1; 282251876Speter } 283251876Speter if (result > 1) { 284251876Speter if (extra > 1) { 285251876Speter result /= divisor; 286251876Speter if (result >= 4096) 287251876Speter result = 0; /* overflow -> 20bits + >12bits */ 288251876Speter else 289251876Speter result *= extra; 290251876Speter } else if (result >= divisor) { 291251876Speter result /= divisor; 292251876Speter } else { 293251876Speter result = 1; 294251876Speter } 295251876Speter } 296251876Speter return result; 297251876Speter} 298251876Speter 299251876Speter 300251876Speterint 301251876Speterget_partition_modifier(void) 302251876Speter{ 303251876Speter int c, result; 304251876Speter 305251876Speter result = 0; 306251876Speter 307251876Speter c = my_getch(); 308251876Speter 309251876Speter if (c == 'p' || c == 'P') 310251876Speter result = 1; 311251876Speter else if (c > 0) 312251876Speter my_ungetch(c); 313251876Speter 314251876Speter return result; 315251876Speter} 316251876Speter 317251876Speter 318251876Speterint 319251876Speternumber_of_digits(unsigned long value) 320251876Speter{ 321251876Speter int j; 322251876Speter 323251876Speter j = 1; 324251876Speter while (value > 9) { 325251876Speter j++; 326251876Speter value = value / 10; 327251876Speter } 328251876Speter return j; 329251876Speter} 330251876Speter 331251876Speter 332251876Speter/* 333251876Speter * Print a message on standard error & flush the input. 334251876Speter */ 335251876Spetervoid 336251876Speterbad_input(const char *fmt,...) 337251876Speter{ 338251876Speter va_list ap; 339251876Speter 340251876Speter va_start(ap, fmt); 341251876Speter vfprintf(stderr, fmt, ap); 342251876Speter va_end(ap); 343251876Speter fprintf(stderr, "\n"); 344251876Speter flush_to_newline(1); 345251876Speter} 346251876Speter