1217309Snwhitehorn/*	$OpenBSD: io.c,v 1.31 2016/02/01 18:55:00 krw Exp $	*/
2224014Snwhitehorn
3217309Snwhitehorn/*
4217309Snwhitehorn * io.c - simple io and input parsing routines
5217309Snwhitehorn *
6220749Snwhitehorn * Written by Eryk Vershen
7217309Snwhitehorn */
8217309Snwhitehorn
9217309Snwhitehorn/*
10217309Snwhitehorn * Copyright 1996,1997,1998 by Apple Computer, Inc.
11217309Snwhitehorn *              All Rights Reserved
12217309Snwhitehorn *
13217309Snwhitehorn * Permission to use, copy, modify, and distribute this software and
14217309Snwhitehorn * its documentation for any purpose and without fee is hereby granted,
15217309Snwhitehorn * provided that the above copyright notice appears in all copies and
16217309Snwhitehorn * that both the copyright notice and this permission notice appear in
17217309Snwhitehorn * supporting documentation.
18217309Snwhitehorn *
19217309Snwhitehorn * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
20217309Snwhitehorn * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21217309Snwhitehorn * FOR A PARTICULAR PURPOSE.
22217309Snwhitehorn *
23217309Snwhitehorn * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
24217309Snwhitehorn * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25217309Snwhitehorn * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
26217309Snwhitehorn * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
27217309Snwhitehorn * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28217309Snwhitehorn */
29217309Snwhitehorn
30217309Snwhitehorn#include <sys/queue.h>
31217309Snwhitehorn
32217309Snwhitehorn#include <err.h>
33217309Snwhitehorn#include <stdio.h>
34217309Snwhitehorn#include <stdlib.h>
35217309Snwhitehorn#include <string.h>
36217309Snwhitehorn#include <stdarg.h>
37217309Snwhitehorn
38217309Snwhitehorn#include "partition_map.h"
39217309Snwhitehorn#include "io.h"
40217309Snwhitehorn
41217309Snwhitehorn#define UNGET_MAX_COUNT 10
42217309Snwhitehorn
43217309Snwhitehornshort	unget_buf[UNGET_MAX_COUNT + 1];
44217309Snwhitehornint	unget_count;
45217309Snwhitehorn
46217309Snwhitehornstatic int	get_number(long *);
47217309Snwhitehornstatic char    *get_string(int);
48217309Snwhitehornstatic int	my_getch (void);
49217309Snwhitehorn
50217309Snwhitehornint
51217309Snwhitehornmy_getch()
52217309Snwhitehorn{
53217309Snwhitehorn	if (unget_count > 0)
54217309Snwhitehorn		return unget_buf[--unget_count];
55217309Snwhitehorn	else
56217309Snwhitehorn		return getc(stdin);
57217309Snwhitehorn}
58217309Snwhitehorn
59217309Snwhitehorn
60217309Snwhitehornvoid
61217309Snwhitehornmy_ungetch(int c)
62217309Snwhitehorn{
63217309Snwhitehorn	/*
64217309Snwhitehorn         * In practice there is never more than one character in
65217309Snwhitehorn         * the unget_buf, but what's a little overkill among friends?
66217309Snwhitehorn         */
67217309Snwhitehorn	if (unget_count < UNGET_MAX_COUNT)
68217309Snwhitehorn		unget_buf[unget_count++] = c;
69217309Snwhitehorn	else
70217309Snwhitehorn		errx(1, "Programmer error in my_ungetch().");
71217309Snwhitehorn}
72217309Snwhitehorn
73217309Snwhitehornvoid
74224014Snwhitehornflush_to_newline(int keep_newline)
75217309Snwhitehorn{
76224014Snwhitehorn	int c;
77217309Snwhitehorn
78217309Snwhitehorn	for (;;) {
79217309Snwhitehorn		c = my_getch();
80217309Snwhitehorn
81217309Snwhitehorn		if (c <= 0) {
82217309Snwhitehorn			break;
83217309Snwhitehorn		} else if (c == '\n') {
84217309Snwhitehorn			if (keep_newline)
85217309Snwhitehorn				my_ungetch(c);
86217309Snwhitehorn			break;
87217309Snwhitehorn		} else {
88217309Snwhitehorn			/* skip */
89217309Snwhitehorn		}
90217309Snwhitehorn	}
91217309Snwhitehorn	return;
92217309Snwhitehorn}
93217309Snwhitehorn
94217309Snwhitehorn
95217309Snwhitehornint
96217309Snwhitehornget_okay(const char *prompt, int default_value)
97217309Snwhitehorn{
98217309Snwhitehorn	int c;
99217309Snwhitehorn
100220749Snwhitehorn	flush_to_newline(0);
101224014Snwhitehorn	printf("%s", prompt);
102217309Snwhitehorn
103217309Snwhitehorn	for (;;) {
104217309Snwhitehorn		c = my_getch();
105217309Snwhitehorn
106217309Snwhitehorn		if (c <= 0) {
107217309Snwhitehorn			break;
108217309Snwhitehorn		} else if (c == ' ' || c == '\t') {
109217309Snwhitehorn			/* skip blanks and tabs */
110217309Snwhitehorn		} else if (c == '\n') {
111217309Snwhitehorn			my_ungetch(c);
112220749Snwhitehorn			return default_value;
113217309Snwhitehorn		} else if (c == 'y' || c == 'Y') {
114217309Snwhitehorn			return 1;
115217309Snwhitehorn		} else if (c == 'n' || c == 'N') {
116220749Snwhitehorn			return 0;
117217309Snwhitehorn		} else {
118217309Snwhitehorn			flush_to_newline(0);
119217309Snwhitehorn			printf("%s", prompt);
120217309Snwhitehorn		}
121217309Snwhitehorn	}
122217309Snwhitehorn	return -1;
123217309Snwhitehorn}
124217309Snwhitehorn
125217309Snwhitehornint
126217309Snwhitehornget_command(const char *prompt, int promptBeforeGet, int *command)
127217309Snwhitehorn{
128217309Snwhitehorn	int c;
129217309Snwhitehorn
130217309Snwhitehorn	if (promptBeforeGet)
131217309Snwhitehorn		printf("%s", prompt);
132217309Snwhitehorn
133217309Snwhitehorn	for (;;) {
134217309Snwhitehorn		c = my_getch();
135217309Snwhitehorn
136217309Snwhitehorn		if (c <= 0) {
137217309Snwhitehorn			break;
138217309Snwhitehorn		} else if (c == ' ' || c == '\t') {
139217309Snwhitehorn			/* skip blanks and tabs */
140217309Snwhitehorn		} else if (c == '\n') {
141217309Snwhitehorn			printf("%s", prompt);
142217309Snwhitehorn		} else {
143224014Snwhitehorn			*command = c;
144217309Snwhitehorn			return 1;
145217309Snwhitehorn		}
146217309Snwhitehorn	}
147217309Snwhitehorn	return 0;
148217309Snwhitehorn}
149217309Snwhitehorn
150217309Snwhitehornint
151217309Snwhitehornget_number_argument(const char *prompt, long *number)
152217309Snwhitehorn{
153217309Snwhitehorn	int c;
154217309Snwhitehorn	int result = 0;
155217309Snwhitehorn
156217309Snwhitehorn	for (;;) {
157217309Snwhitehorn		c = my_getch();
158217309Snwhitehorn
159217309Snwhitehorn		if (c <= 0) {
160217309Snwhitehorn			break;
161217309Snwhitehorn		} else if (c == ' ' || c == '\t') {
162217309Snwhitehorn			/* skip blanks and tabs */
163217309Snwhitehorn		} else if (c == '\n') {
164217309Snwhitehorn			printf("%s", prompt);
165217309Snwhitehorn		} else if ('0' <= c && c <= '9') {
166217309Snwhitehorn			my_ungetch(c);
167217309Snwhitehorn			result = get_number(number);
168217309Snwhitehorn			break;
169217309Snwhitehorn		} else {
170217309Snwhitehorn			my_ungetch(c);
171217309Snwhitehorn			*number = 0;
172217309Snwhitehorn			break;
173217309Snwhitehorn		}
174217309Snwhitehorn	}
175217309Snwhitehorn	return result;
176217309Snwhitehorn}
177217309Snwhitehorn
178217309Snwhitehorn
179217309Snwhitehornint
180217309Snwhitehornget_number(long *number)
181217309Snwhitehorn{
182217309Snwhitehorn	long value;
183217309Snwhitehorn	int c;
184217309Snwhitehorn
185217309Snwhitehorn	value = 0;
186217309Snwhitehorn	while ((c = my_getch())) {
187217309Snwhitehorn		if (c >= '0' && c <= '9') {
188217309Snwhitehorn			value = value * 10 + (c - '0');
189217309Snwhitehorn		} else if (c == ' ' || c == '\t' || c == '\n') {
190217309Snwhitehorn			my_ungetch(c);
191217309Snwhitehorn			*number = value;
192217309Snwhitehorn			return 1;
193217309Snwhitehorn		} else {
194217309Snwhitehorn			return 0;
195217309Snwhitehorn		}
196217309Snwhitehorn	}
197217309Snwhitehorn
198217309Snwhitehorn	return 0;
199217309Snwhitehorn}
200217309Snwhitehorn
201217309Snwhitehornchar *
202217309Snwhitehornget_dpistr_argument(const char *prompt)
203217309Snwhitehorn{
204217309Snwhitehorn	int c;
205217309Snwhitehorn
206217309Snwhitehorn	for (;;) {
207217309Snwhitehorn		c = my_getch();
208217309Snwhitehorn
209217309Snwhitehorn		if (c <= 0) {
210217309Snwhitehorn			break;
211217309Snwhitehorn		} else if (c == ' ' || c == '\t') {
212217309Snwhitehorn			/* skip blanks and tabs */
213217309Snwhitehorn		} else if (c == '\n') {
214217309Snwhitehorn			printf("%s", prompt);
215217309Snwhitehorn		} else if (c == '"' || c == '\'') {
216217309Snwhitehorn			return get_string(c);
217217309Snwhitehorn		} else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
218217309Snwhitehorn		    (c == '-' || c == '/' || c == '.' || c == ':')) {
219217309Snwhitehorn			my_ungetch(c);
220217309Snwhitehorn			return get_string(' ');
221217309Snwhitehorn		} else {
222224014Snwhitehorn			my_ungetch(c);
223224014Snwhitehorn			return NULL;
224217309Snwhitehorn		}
225217309Snwhitehorn	}
226217309Snwhitehorn	return NULL;
227217309Snwhitehorn}
228217309Snwhitehorn
229217309Snwhitehorn
230217309Snwhitehornchar *
231217309Snwhitehornget_string(int eos)
232217309Snwhitehorn{
233217309Snwhitehorn	char buf[DPISTRLEN+1];
234217309Snwhitehorn	char *s, *limit;
235217309Snwhitehorn	int c;
236217309Snwhitehorn
237217309Snwhitehorn	memset(buf, 0, sizeof(buf));
238217309Snwhitehorn	limit = buf + sizeof(buf);
239217309Snwhitehorn
240217309Snwhitehorn	c = my_getch();
241217309Snwhitehorn	for (s = buf;; c = my_getch()) {
242217309Snwhitehorn		if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) {
243217309Snwhitehorn			*s = 0;
244217309Snwhitehorn			break;
245217309Snwhitehorn		} else if (c == '\n') {
246217309Snwhitehorn			*s = 0;
247220749Snwhitehorn			my_ungetch(c);
248224014Snwhitehorn			break;
249217309Snwhitehorn		} else {
250217309Snwhitehorn			*s++ = c;
251217309Snwhitehorn			if (s >= limit)
252217309Snwhitehorn				return NULL;
253217309Snwhitehorn		}
254217309Snwhitehorn	}
255217309Snwhitehorn	return strdup(buf);
256217309Snwhitehorn}
257217309Snwhitehorn
258217309Snwhitehorn
259217309Snwhitehornunsigned long
260220749Snwhitehornget_multiplier(long divisor)
261217309Snwhitehorn{
262217309Snwhitehorn	unsigned long result, extra;
263217309Snwhitehorn	int c;
264220749Snwhitehorn
265220749Snwhitehorn	c = my_getch();
266217309Snwhitehorn
267217309Snwhitehorn	extra = 1;
268217309Snwhitehorn	if (c <= 0 || divisor <= 0) {
269217309Snwhitehorn		result = 0;
270217309Snwhitehorn	} else if (c == 't' || c == 'T') {
271217309Snwhitehorn		result = 1024 * 1024;
272217309Snwhitehorn		extra = 1024 * 1024;
273217309Snwhitehorn	} else if (c == 'g' || c == 'G') {
274217309Snwhitehorn		result = 1024 * 1024 * 1024;
275217309Snwhitehorn	} else if (c == 'm' || c == 'M') {
276217309Snwhitehorn		result = 1024 * 1024;
277217309Snwhitehorn	} else if (c == 'k' || c == 'K') {
278217309Snwhitehorn		result = 1024;
279217309Snwhitehorn	} else {
280217309Snwhitehorn		my_ungetch(c);
281217309Snwhitehorn		result = 1;
282217309Snwhitehorn	}
283217309Snwhitehorn	if (result > 1) {
284217309Snwhitehorn		if (extra > 1) {
285217309Snwhitehorn			result /= divisor;
286217309Snwhitehorn			if (result >= 4096)
287217309Snwhitehorn				result = 0; /* overflow -> 20bits + >12bits */
288217309Snwhitehorn			else
289217309Snwhitehorn				result *= extra;
290217309Snwhitehorn		} else if (result >= divisor) {
291224014Snwhitehorn			result /= divisor;
292217309Snwhitehorn		} else {
293217309Snwhitehorn			result = 1;
294217309Snwhitehorn		}
295217309Snwhitehorn	}
296217309Snwhitehorn	return result;
297217309Snwhitehorn}
298217309Snwhitehorn
299217309Snwhitehorn
300217309Snwhitehornint
301217309Snwhitehornget_partition_modifier(void)
302217309Snwhitehorn{
303217309Snwhitehorn	int c, result;
304217309Snwhitehorn
305217309Snwhitehorn	result = 0;
306217309Snwhitehorn
307217309Snwhitehorn	c = my_getch();
308217309Snwhitehorn
309217309Snwhitehorn	if (c == 'p' || c == 'P')
310217309Snwhitehorn		result = 1;
311217309Snwhitehorn	else if (c > 0)
312217309Snwhitehorn		my_ungetch(c);
313217309Snwhitehorn
314217309Snwhitehorn	return result;
315217309Snwhitehorn}
316217309Snwhitehorn
317217309Snwhitehorn
318217309Snwhitehornint
319217309Snwhitehornnumber_of_digits(unsigned long value)
320217309Snwhitehorn{
321217309Snwhitehorn	int j;
322217309Snwhitehorn
323217309Snwhitehorn	j = 1;
324217309Snwhitehorn	while (value > 9) {
325217309Snwhitehorn		j++;
326217309Snwhitehorn		value = value / 10;
327217309Snwhitehorn	}
328217309Snwhitehorn	return j;
329217309Snwhitehorn}
330217309Snwhitehorn
331217309Snwhitehorn
332220749Snwhitehorn/*
333217309Snwhitehorn * Print a message on standard error & flush the input.
334217309Snwhitehorn */
335217309Snwhitehornvoid
336217309Snwhitehornbad_input(const char *fmt,...)
337217309Snwhitehorn{
338220749Snwhitehorn	va_list ap;
339217309Snwhitehorn
340217309Snwhitehorn	va_start(ap, fmt);
341217309Snwhitehorn	vfprintf(stderr, fmt, ap);
342217309Snwhitehorn	va_end(ap);
343217309Snwhitehorn	fprintf(stderr, "\n");
344217309Snwhitehorn	flush_to_newline(1);
345217309Snwhitehorn}
346217309Snwhitehorn