1*4a47b700Skrw /* $OpenBSD: io.c,v 1.31 2016/02/01 18:55:00 krw Exp $ */
2fb04e59aSjasper
386ec409aSkrw /*
486ec409aSkrw * io.c - simple io and input parsing routines
586ec409aSkrw *
686ec409aSkrw * Written by Eryk Vershen
786ec409aSkrw */
8dce63815Sdrahn
9dce63815Sdrahn /*
10dce63815Sdrahn * Copyright 1996,1997,1998 by Apple Computer, Inc.
11dce63815Sdrahn * All Rights Reserved
12dce63815Sdrahn *
13dce63815Sdrahn * Permission to use, copy, modify, and distribute this software and
14dce63815Sdrahn * its documentation for any purpose and without fee is hereby granted,
15dce63815Sdrahn * provided that the above copyright notice appears in all copies and
16dce63815Sdrahn * that both the copyright notice and this permission notice appear in
17dce63815Sdrahn * supporting documentation.
18dce63815Sdrahn *
19dce63815Sdrahn * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
20dce63815Sdrahn * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21dce63815Sdrahn * FOR A PARTICULAR PURPOSE.
22dce63815Sdrahn *
23dce63815Sdrahn * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
24dce63815Sdrahn * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25dce63815Sdrahn * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
26dce63815Sdrahn * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
27dce63815Sdrahn * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28dce63815Sdrahn */
29dce63815Sdrahn
30a63f2390Skrw #include <sys/queue.h>
31a63f2390Skrw
3268d0f91bSkrw #include <err.h>
33dce63815Sdrahn #include <stdio.h>
34dce63815Sdrahn #include <stdlib.h>
35dce63815Sdrahn #include <string.h>
36dce63815Sdrahn #include <stdarg.h>
37dce63815Sdrahn
38a63f2390Skrw #include "partition_map.h"
39dce63815Sdrahn #include "io.h"
40dce63815Sdrahn
41dce63815Sdrahn #define UNGET_MAX_COUNT 10
42dce63815Sdrahn
43dce63815Sdrahn short unget_buf[UNGET_MAX_COUNT + 1];
44dce63815Sdrahn int unget_count;
45dce63815Sdrahn
4632401e4bSkrw static int get_number(long *);
478799a2d3Skrw static char *get_string(int);
488799a2d3Skrw static int my_getch (void);
49dce63815Sdrahn
50dce63815Sdrahn int
my_getch()51dce63815Sdrahn my_getch()
52dce63815Sdrahn {
53a8b53b4cSkrw if (unget_count > 0)
54106ae2cbSkrw return unget_buf[--unget_count];
55a8b53b4cSkrw else
56106ae2cbSkrw return getc(stdin);
57dce63815Sdrahn }
58dce63815Sdrahn
59dce63815Sdrahn
60dce63815Sdrahn void
my_ungetch(int c)61dce63815Sdrahn my_ungetch(int c)
62dce63815Sdrahn {
6386ec409aSkrw /*
6486ec409aSkrw * In practice there is never more than one character in
6586ec409aSkrw * the unget_buf, but what's a little overkill among friends?
6686ec409aSkrw */
67a8b53b4cSkrw if (unget_count < UNGET_MAX_COUNT)
68dce63815Sdrahn unget_buf[unget_count++] = c;
69a8b53b4cSkrw else
7068d0f91bSkrw errx(1, "Programmer error in my_ungetch().");
71dce63815Sdrahn }
72dce63815Sdrahn
73dce63815Sdrahn void
flush_to_newline(int keep_newline)74dce63815Sdrahn flush_to_newline(int keep_newline)
75dce63815Sdrahn {
76dce63815Sdrahn int c;
77dce63815Sdrahn
78dce63815Sdrahn for (;;) {
79dce63815Sdrahn c = my_getch();
80dce63815Sdrahn
81dce63815Sdrahn if (c <= 0) {
82dce63815Sdrahn break;
83dce63815Sdrahn } else if (c == '\n') {
845046737fSkrw if (keep_newline)
85dce63815Sdrahn my_ungetch(c);
86dce63815Sdrahn break;
87dce63815Sdrahn } else {
8886ec409aSkrw /* skip */
89dce63815Sdrahn }
90dce63815Sdrahn }
91dce63815Sdrahn return;
92dce63815Sdrahn }
93dce63815Sdrahn
94dce63815Sdrahn
95dce63815Sdrahn int
get_okay(const char * prompt,int default_value)96b42d9302Smartin get_okay(const char *prompt, int default_value)
97dce63815Sdrahn {
98dce63815Sdrahn int c;
99dce63815Sdrahn
100dce63815Sdrahn flush_to_newline(0);
101*4a47b700Skrw printf("%s", prompt);
102dce63815Sdrahn
103dce63815Sdrahn for (;;) {
104dce63815Sdrahn c = my_getch();
105dce63815Sdrahn
106dce63815Sdrahn if (c <= 0) {
107dce63815Sdrahn break;
108dce63815Sdrahn } else if (c == ' ' || c == '\t') {
10986ec409aSkrw /* skip blanks and tabs */
110dce63815Sdrahn } else if (c == '\n') {
111dce63815Sdrahn my_ungetch(c);
112dce63815Sdrahn return default_value;
113dce63815Sdrahn } else if (c == 'y' || c == 'Y') {
114dce63815Sdrahn return 1;
115dce63815Sdrahn } else if (c == 'n' || c == 'N') {
116dce63815Sdrahn return 0;
117dce63815Sdrahn } else {
118dce63815Sdrahn flush_to_newline(0);
119*4a47b700Skrw printf("%s", prompt);
120dce63815Sdrahn }
121dce63815Sdrahn }
122dce63815Sdrahn return -1;
123dce63815Sdrahn }
124dce63815Sdrahn
125dce63815Sdrahn int
get_command(const char * prompt,int promptBeforeGet,int * command)126b42d9302Smartin get_command(const char *prompt, int promptBeforeGet, int *command)
127dce63815Sdrahn {
128dce63815Sdrahn int c;
129dce63815Sdrahn
130a8b53b4cSkrw if (promptBeforeGet)
131*4a47b700Skrw printf("%s", prompt);
132a8b53b4cSkrw
133dce63815Sdrahn for (;;) {
134dce63815Sdrahn c = my_getch();
135dce63815Sdrahn
136dce63815Sdrahn if (c <= 0) {
137dce63815Sdrahn break;
138dce63815Sdrahn } else if (c == ' ' || c == '\t') {
13986ec409aSkrw /* skip blanks and tabs */
140dce63815Sdrahn } else if (c == '\n') {
141*4a47b700Skrw printf("%s", prompt);
142dce63815Sdrahn } else {
143dce63815Sdrahn *command = c;
144dce63815Sdrahn return 1;
145dce63815Sdrahn }
146dce63815Sdrahn }
147dce63815Sdrahn return 0;
148dce63815Sdrahn }
149dce63815Sdrahn
150dce63815Sdrahn int
get_number_argument(const char * prompt,long * number)15167ac1252Skrw get_number_argument(const char *prompt, long *number)
152dce63815Sdrahn {
153dce63815Sdrahn int c;
154dce63815Sdrahn int result = 0;
155dce63815Sdrahn
156dce63815Sdrahn for (;;) {
157dce63815Sdrahn c = my_getch();
158dce63815Sdrahn
159dce63815Sdrahn if (c <= 0) {
160dce63815Sdrahn break;
161dce63815Sdrahn } else if (c == ' ' || c == '\t') {
16286ec409aSkrw /* skip blanks and tabs */
163dce63815Sdrahn } else if (c == '\n') {
164*4a47b700Skrw printf("%s", prompt);
165dce63815Sdrahn } else if ('0' <= c && c <= '9') {
16632401e4bSkrw my_ungetch(c);
16732401e4bSkrw result = get_number(number);
168dce63815Sdrahn break;
169dce63815Sdrahn } else {
170dce63815Sdrahn my_ungetch(c);
171dce63815Sdrahn *number = 0;
172dce63815Sdrahn break;
173dce63815Sdrahn }
174dce63815Sdrahn }
175dce63815Sdrahn return result;
176dce63815Sdrahn }
177dce63815Sdrahn
178dce63815Sdrahn
17932401e4bSkrw int
get_number(long * number)18032401e4bSkrw get_number(long *number)
181dce63815Sdrahn {
18232401e4bSkrw long value;
18332401e4bSkrw int c;
184dce63815Sdrahn
18532401e4bSkrw value = 0;
18632401e4bSkrw while ((c = my_getch())) {
18732401e4bSkrw if (c >= '0' && c <= '9') {
18832401e4bSkrw value = value * 10 + (c - '0');
18932401e4bSkrw } else if (c == ' ' || c == '\t' || c == '\n') {
19032401e4bSkrw my_ungetch(c);
19132401e4bSkrw *number = value;
19232401e4bSkrw return 1;
193dce63815Sdrahn } else {
19432401e4bSkrw return 0;
195dce63815Sdrahn }
196dce63815Sdrahn }
19732401e4bSkrw
19832401e4bSkrw return 0;
199dce63815Sdrahn }
200dce63815Sdrahn
2018799a2d3Skrw char *
get_dpistr_argument(const char * prompt)2028799a2d3Skrw get_dpistr_argument(const char *prompt)
203dce63815Sdrahn {
204dce63815Sdrahn int c;
205dce63815Sdrahn
206dce63815Sdrahn for (;;) {
207dce63815Sdrahn c = my_getch();
208dce63815Sdrahn
209dce63815Sdrahn if (c <= 0) {
210dce63815Sdrahn break;
211dce63815Sdrahn } else if (c == ' ' || c == '\t') {
21286ec409aSkrw /* skip blanks and tabs */
213dce63815Sdrahn } else if (c == '\n') {
214*4a47b700Skrw printf("%s", prompt);
215dce63815Sdrahn } else if (c == '"' || c == '\'') {
2168799a2d3Skrw return get_string(c);
217a8b53b4cSkrw } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
218a8b53b4cSkrw (c == '-' || c == '/' || c == '.' || c == ':')) {
219dce63815Sdrahn my_ungetch(c);
2208799a2d3Skrw return get_string(' ');
221dce63815Sdrahn } else {
222dce63815Sdrahn my_ungetch(c);
2238799a2d3Skrw return NULL;
224dce63815Sdrahn }
225dce63815Sdrahn }
2268799a2d3Skrw return NULL;
227dce63815Sdrahn }
228dce63815Sdrahn
229dce63815Sdrahn
230dce63815Sdrahn char *
get_string(int eos)231dce63815Sdrahn get_string(int eos)
232dce63815Sdrahn {
233f4081a22Skrw char buf[DPISTRLEN+1];
2348799a2d3Skrw char *s, *limit;
2358799a2d3Skrw int c;
236dce63815Sdrahn
2378799a2d3Skrw memset(buf, 0, sizeof(buf));
2388799a2d3Skrw limit = buf + sizeof(buf);
239dce63815Sdrahn
240dce63815Sdrahn c = my_getch();
2418799a2d3Skrw for (s = buf;; c = my_getch()) {
242dce63815Sdrahn if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) {
2438799a2d3Skrw *s = 0;
244dce63815Sdrahn break;
245dce63815Sdrahn } else if (c == '\n') {
2468799a2d3Skrw *s = 0;
247dce63815Sdrahn my_ungetch(c);
248dce63815Sdrahn break;
249dce63815Sdrahn } else {
250dce63815Sdrahn *s++ = c;
2518799a2d3Skrw if (s >= limit)
2528799a2d3Skrw return NULL;
253dce63815Sdrahn }
254dce63815Sdrahn }
255106ae2cbSkrw return strdup(buf);
256dce63815Sdrahn }
257dce63815Sdrahn
258dce63815Sdrahn
259dce63815Sdrahn unsigned long
get_multiplier(long divisor)260dce63815Sdrahn get_multiplier(long divisor)
261dce63815Sdrahn {
262928e0d77Skrw unsigned long result, extra;
263dce63815Sdrahn int c;
264dce63815Sdrahn
265dce63815Sdrahn c = my_getch();
266dce63815Sdrahn
267dce63815Sdrahn extra = 1;
268dce63815Sdrahn if (c <= 0 || divisor <= 0) {
269dce63815Sdrahn result = 0;
270dce63815Sdrahn } else if (c == 't' || c == 'T') {
271dce63815Sdrahn result = 1024 * 1024;
272dce63815Sdrahn extra = 1024 * 1024;
273dce63815Sdrahn } else if (c == 'g' || c == 'G') {
274dce63815Sdrahn result = 1024 * 1024 * 1024;
275dce63815Sdrahn } else if (c == 'm' || c == 'M') {
276dce63815Sdrahn result = 1024 * 1024;
277dce63815Sdrahn } else if (c == 'k' || c == 'K') {
278dce63815Sdrahn result = 1024;
279dce63815Sdrahn } else {
280dce63815Sdrahn my_ungetch(c);
281dce63815Sdrahn result = 1;
282dce63815Sdrahn }
283dce63815Sdrahn if (result > 1) {
284dce63815Sdrahn if (extra > 1) {
285dce63815Sdrahn result /= divisor;
2865046737fSkrw if (result >= 4096)
2875046737fSkrw result = 0; /* overflow -> 20bits + >12bits */
2885046737fSkrw else
289dce63815Sdrahn result *= extra;
290dce63815Sdrahn } else if (result >= divisor) {
291dce63815Sdrahn result /= divisor;
292dce63815Sdrahn } else {
293dce63815Sdrahn result = 1;
294dce63815Sdrahn }
295dce63815Sdrahn }
296dce63815Sdrahn return result;
297dce63815Sdrahn }
298dce63815Sdrahn
299dce63815Sdrahn
300dce63815Sdrahn int
get_partition_modifier(void)301dce63815Sdrahn get_partition_modifier(void)
302dce63815Sdrahn {
303928e0d77Skrw int c, result;
304dce63815Sdrahn
305dce63815Sdrahn result = 0;
306dce63815Sdrahn
307dce63815Sdrahn c = my_getch();
308dce63815Sdrahn
309a8b53b4cSkrw if (c == 'p' || c == 'P')
310dce63815Sdrahn result = 1;
311a8b53b4cSkrw else if (c > 0)
312dce63815Sdrahn my_ungetch(c);
313a8b53b4cSkrw
314dce63815Sdrahn return result;
315dce63815Sdrahn }
316dce63815Sdrahn
317dce63815Sdrahn
318dce63815Sdrahn int
number_of_digits(unsigned long value)319dce63815Sdrahn number_of_digits(unsigned long value)
320dce63815Sdrahn {
321dce63815Sdrahn int j;
322dce63815Sdrahn
323dce63815Sdrahn j = 1;
324dce63815Sdrahn while (value > 9) {
325dce63815Sdrahn j++;
326dce63815Sdrahn value = value / 10;
327dce63815Sdrahn }
328dce63815Sdrahn return j;
329dce63815Sdrahn }
330dce63815Sdrahn
331dce63815Sdrahn
33286ec409aSkrw /*
33386ec409aSkrw * Print a message on standard error & flush the input.
33486ec409aSkrw */
335dce63815Sdrahn void
bad_input(const char * fmt,...)336b42d9302Smartin bad_input(const char *fmt,...)
337dce63815Sdrahn {
338dce63815Sdrahn va_list ap;
339dce63815Sdrahn
340dce63815Sdrahn va_start(ap, fmt);
341dce63815Sdrahn vfprintf(stderr, fmt, ap);
342dce63815Sdrahn va_end(ap);
343dce63815Sdrahn fprintf(stderr, "\n");
344dce63815Sdrahn flush_to_newline(1);
345dce63815Sdrahn }
346