1 /* $OpenBSD: io.c,v 1.31 2016/02/01 18:55:00 krw Exp $ */
2
3 /*
4 * io.c - simple io and input parsing routines
5 *
6 * Written by Eryk Vershen
7 */
8
9 /*
10 * Copyright 1996,1997,1998 by Apple Computer, Inc.
11 * All Rights Reserved
12 *
13 * Permission to use, copy, modify, and distribute this software and
14 * its documentation for any purpose and without fee is hereby granted,
15 * provided that the above copyright notice appears in all copies and
16 * that both the copyright notice and this permission notice appear in
17 * supporting documentation.
18 *
19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE.
22 *
23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 */
29
30 #include <sys/queue.h>
31
32 #include <err.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdarg.h>
37
38 #include "partition_map.h"
39 #include "io.h"
40
41 #define UNGET_MAX_COUNT 10
42
43 short unget_buf[UNGET_MAX_COUNT + 1];
44 int unget_count;
45
46 static int get_number(long *);
47 static char *get_string(int);
48 static int my_getch (void);
49
50 int
my_getch()51 my_getch()
52 {
53 if (unget_count > 0)
54 return unget_buf[--unget_count];
55 else
56 return getc(stdin);
57 }
58
59
60 void
my_ungetch(int c)61 my_ungetch(int c)
62 {
63 /*
64 * In practice there is never more than one character in
65 * the unget_buf, but what's a little overkill among friends?
66 */
67 if (unget_count < UNGET_MAX_COUNT)
68 unget_buf[unget_count++] = c;
69 else
70 errx(1, "Programmer error in my_ungetch().");
71 }
72
73 void
flush_to_newline(int keep_newline)74 flush_to_newline(int keep_newline)
75 {
76 int c;
77
78 for (;;) {
79 c = my_getch();
80
81 if (c <= 0) {
82 break;
83 } else if (c == '\n') {
84 if (keep_newline)
85 my_ungetch(c);
86 break;
87 } else {
88 /* skip */
89 }
90 }
91 return;
92 }
93
94
95 int
get_okay(const char * prompt,int default_value)96 get_okay(const char *prompt, int default_value)
97 {
98 int c;
99
100 flush_to_newline(0);
101 printf("%s", prompt);
102
103 for (;;) {
104 c = my_getch();
105
106 if (c <= 0) {
107 break;
108 } else if (c == ' ' || c == '\t') {
109 /* skip blanks and tabs */
110 } else if (c == '\n') {
111 my_ungetch(c);
112 return default_value;
113 } else if (c == 'y' || c == 'Y') {
114 return 1;
115 } else if (c == 'n' || c == 'N') {
116 return 0;
117 } else {
118 flush_to_newline(0);
119 printf("%s", prompt);
120 }
121 }
122 return -1;
123 }
124
125 int
get_command(const char * prompt,int promptBeforeGet,int * command)126 get_command(const char *prompt, int promptBeforeGet, int *command)
127 {
128 int c;
129
130 if (promptBeforeGet)
131 printf("%s", prompt);
132
133 for (;;) {
134 c = my_getch();
135
136 if (c <= 0) {
137 break;
138 } else if (c == ' ' || c == '\t') {
139 /* skip blanks and tabs */
140 } else if (c == '\n') {
141 printf("%s", prompt);
142 } else {
143 *command = c;
144 return 1;
145 }
146 }
147 return 0;
148 }
149
150 int
get_number_argument(const char * prompt,long * number)151 get_number_argument(const char *prompt, long *number)
152 {
153 int c;
154 int result = 0;
155
156 for (;;) {
157 c = my_getch();
158
159 if (c <= 0) {
160 break;
161 } else if (c == ' ' || c == '\t') {
162 /* skip blanks and tabs */
163 } else if (c == '\n') {
164 printf("%s", prompt);
165 } else if ('0' <= c && c <= '9') {
166 my_ungetch(c);
167 result = get_number(number);
168 break;
169 } else {
170 my_ungetch(c);
171 *number = 0;
172 break;
173 }
174 }
175 return result;
176 }
177
178
179 int
get_number(long * number)180 get_number(long *number)
181 {
182 long value;
183 int c;
184
185 value = 0;
186 while ((c = my_getch())) {
187 if (c >= '0' && c <= '9') {
188 value = value * 10 + (c - '0');
189 } else if (c == ' ' || c == '\t' || c == '\n') {
190 my_ungetch(c);
191 *number = value;
192 return 1;
193 } else {
194 return 0;
195 }
196 }
197
198 return 0;
199 }
200
201 char *
get_dpistr_argument(const char * prompt)202 get_dpistr_argument(const char *prompt)
203 {
204 int c;
205
206 for (;;) {
207 c = my_getch();
208
209 if (c <= 0) {
210 break;
211 } else if (c == ' ' || c == '\t') {
212 /* skip blanks and tabs */
213 } else if (c == '\n') {
214 printf("%s", prompt);
215 } else if (c == '"' || c == '\'') {
216 return get_string(c);
217 } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
218 (c == '-' || c == '/' || c == '.' || c == ':')) {
219 my_ungetch(c);
220 return get_string(' ');
221 } else {
222 my_ungetch(c);
223 return NULL;
224 }
225 }
226 return NULL;
227 }
228
229
230 char *
get_string(int eos)231 get_string(int eos)
232 {
233 char buf[DPISTRLEN+1];
234 char *s, *limit;
235 int c;
236
237 memset(buf, 0, sizeof(buf));
238 limit = buf + sizeof(buf);
239
240 c = my_getch();
241 for (s = buf;; c = my_getch()) {
242 if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) {
243 *s = 0;
244 break;
245 } else if (c == '\n') {
246 *s = 0;
247 my_ungetch(c);
248 break;
249 } else {
250 *s++ = c;
251 if (s >= limit)
252 return NULL;
253 }
254 }
255 return strdup(buf);
256 }
257
258
259 unsigned long
get_multiplier(long divisor)260 get_multiplier(long divisor)
261 {
262 unsigned long result, extra;
263 int c;
264
265 c = my_getch();
266
267 extra = 1;
268 if (c <= 0 || divisor <= 0) {
269 result = 0;
270 } else if (c == 't' || c == 'T') {
271 result = 1024 * 1024;
272 extra = 1024 * 1024;
273 } else if (c == 'g' || c == 'G') {
274 result = 1024 * 1024 * 1024;
275 } else if (c == 'm' || c == 'M') {
276 result = 1024 * 1024;
277 } else if (c == 'k' || c == 'K') {
278 result = 1024;
279 } else {
280 my_ungetch(c);
281 result = 1;
282 }
283 if (result > 1) {
284 if (extra > 1) {
285 result /= divisor;
286 if (result >= 4096)
287 result = 0; /* overflow -> 20bits + >12bits */
288 else
289 result *= extra;
290 } else if (result >= divisor) {
291 result /= divisor;
292 } else {
293 result = 1;
294 }
295 }
296 return result;
297 }
298
299
300 int
get_partition_modifier(void)301 get_partition_modifier(void)
302 {
303 int c, result;
304
305 result = 0;
306
307 c = my_getch();
308
309 if (c == 'p' || c == 'P')
310 result = 1;
311 else if (c > 0)
312 my_ungetch(c);
313
314 return result;
315 }
316
317
318 int
number_of_digits(unsigned long value)319 number_of_digits(unsigned long value)
320 {
321 int j;
322
323 j = 1;
324 while (value > 9) {
325 j++;
326 value = value / 10;
327 }
328 return j;
329 }
330
331
332 /*
333 * Print a message on standard error & flush the input.
334 */
335 void
bad_input(const char * fmt,...)336 bad_input(const char *fmt,...)
337 {
338 va_list ap;
339
340 va_start(ap, fmt);
341 vfprintf(stderr, fmt, ap);
342 va_end(ap);
343 fprintf(stderr, "\n");
344 flush_to_newline(1);
345 }
346