xref: /openbsd-src/sbin/pdisk/io.c (revision 4a47b7007300466a5f6f015c999fb6414d7e0ac4)
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