/* $OpenBSD: io.c,v 1.27 2016/01/27 16:38:37 krw Exp $ */ /* * io.c - simple io and input parsing routines * * Written by Eryk Vershen */ /* * Copyright 1996,1997,1998 by Apple Computer, Inc. * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appears in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "dpme.h" #include "io.h" #define BAD_DIGIT 17 /* must be greater than any base */ #define UNGET_MAX_COUNT 10 short unget_buf[UNGET_MAX_COUNT + 1]; int unget_count; static long get_number(int); static char *get_string(int); static int my_getch (void); int my_getch() { if (unget_count > 0) return (unget_buf[--unget_count]); else return (getc(stdin)); } void my_ungetch(int c) { /* * In practice there is never more than one character in * the unget_buf, but what's a little overkill among friends? */ if (unget_count < UNGET_MAX_COUNT) unget_buf[unget_count++] = c; else errx(1, "Programmer error in my_ungetch()."); } void flush_to_newline(int keep_newline) { int c; for (;;) { c = my_getch(); if (c <= 0) { break; } else if (c == '\n') { if (keep_newline) my_ungetch(c); break; } else { /* skip */ } } return; } int get_okay(const char *prompt, int default_value) { int c; flush_to_newline(0); printf(prompt); for (;;) { c = my_getch(); if (c <= 0) { break; } else if (c == ' ' || c == '\t') { /* skip blanks and tabs */ } else if (c == '\n') { my_ungetch(c); return default_value; } else if (c == 'y' || c == 'Y') { return 1; } else if (c == 'n' || c == 'N') { return 0; } else { flush_to_newline(0); printf(prompt); } } return -1; } int get_command(const char *prompt, int promptBeforeGet, int *command) { int c; if (promptBeforeGet) printf(prompt); for (;;) { c = my_getch(); if (c <= 0) { break; } else if (c == ' ' || c == '\t') { /* skip blanks and tabs */ } else if (c == '\n') { printf(prompt); } else { *command = c; return 1; } } return 0; } int get_number_argument(const char *prompt, long *number) { int c; int result = 0; for (;;) { c = my_getch(); if (c <= 0) { break; } else if (c == ' ' || c == '\t') { /* skip blanks and tabs */ } else if (c == '\n') { printf(prompt); } else if ('0' <= c && c <= '9') { *number = get_number(c); result = 1; break; } else { my_ungetch(c); *number = 0; break; } } return result; } long get_number(int first_char) { int c, base, digit, ret_value; if (first_char != '0') { c = first_char; base = 10; digit = BAD_DIGIT; } else if ((c = my_getch()) == 'x' || c == 'X') { c = my_getch(); base = 16; digit = BAD_DIGIT; } else { my_ungetch(c); c = first_char; base = 8; digit = 0; } ret_value = 0; for (ret_value = 0;; c = my_getch()) { if (c >= '0' && c <= '9') digit = c - '0'; else if (c >= 'A' && c <= 'F') digit = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') digit = 10 + (c - 'a'); else digit = BAD_DIGIT; if (digit >= base) break; ret_value = ret_value * base + digit; } my_ungetch(c); return (ret_value); } char * get_dpistr_argument(const char *prompt) { int c; for (;;) { c = my_getch(); if (c <= 0) { break; } else if (c == ' ' || c == '\t') { /* skip blanks and tabs */ } else if (c == '\n') { printf(prompt); } else if (c == '"' || c == '\'') { return get_string(c); } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '-' || c == '/' || c == '.' || c == ':')) { my_ungetch(c); return get_string(' '); } else { my_ungetch(c); return NULL; } } return NULL; } char * get_string(int eos) { char buf[DPISTRLEN+1]; char *s, *limit; int c; memset(buf, 0, sizeof(buf)); limit = buf + sizeof(buf); c = my_getch(); for (s = buf;; c = my_getch()) { if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) { *s = 0; break; } else if (c == '\n') { *s = 0; my_ungetch(c); break; } else { *s++ = c; if (s >= limit) return NULL; } } return (strdup(buf)); } unsigned long get_multiplier(long divisor) { unsigned long result, extra; int c; c = my_getch(); extra = 1; if (c <= 0 || divisor <= 0) { result = 0; } else if (c == 't' || c == 'T') { result = 1024 * 1024; extra = 1024 * 1024; } else if (c == 'g' || c == 'G') { result = 1024 * 1024 * 1024; } else if (c == 'm' || c == 'M') { result = 1024 * 1024; } else if (c == 'k' || c == 'K') { result = 1024; } else { my_ungetch(c); result = 1; } if (result > 1) { if (extra > 1) { result /= divisor; if (result >= 4096) result = 0; /* overflow -> 20bits + >12bits */ else result *= extra; } else if (result >= divisor) { result /= divisor; } else { result = 1; } } return result; } int get_partition_modifier(void) { int c, result; result = 0; c = my_getch(); if (c == 'p' || c == 'P') result = 1; else if (c > 0) my_ungetch(c); return result; } int number_of_digits(unsigned long value) { int j; j = 1; while (value > 9) { j++; value = value / 10; } return j; } /* * Print a message on standard error & flush the input. */ void bad_input(const char *fmt,...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); flush_to_newline(1); }