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