1/*	$OpenBSD: getpar.c,v 1.15 2016/01/07 14:37:51 mestre Exp $	*/
2/*	$NetBSD: getpar.c,v 1.4 1995/04/24 12:25:57 cgd Exp $	*/
3
4/*
5 * Copyright (c) 1980, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36
37#include "getpar.h"
38#include "trek.h"
39
40static int testterm(void);
41
42/**
43 **	get integer parameter
44 **/
45
46int
47getintpar(const char *s)
48{
49	int	i, n;
50
51	while (1)
52	{
53		if (testnl() && s)
54			printf("%s: ", s);
55		i = scanf("%d", &n);
56		if (i < 0)
57			exit(1);
58		if (i > 0 && testterm())
59			return (n);
60		printf("invalid input; please enter an integer\n");
61		skiptonl(0);
62	}
63}
64
65/**
66 **	get floating parameter
67 **/
68
69double
70getfltpar(const char *s)
71{
72	int		i;
73	double		d;
74
75	while (1)
76	{
77		if (testnl() && s)
78			printf("%s: ", s);
79		i = scanf("%lf", &d);
80		if (i < 0)
81			exit(1);
82		if (i > 0 && testterm())
83			return (d);
84		printf("invalid input; please enter a double\n");
85		skiptonl(0);
86	}
87}
88
89/**
90 **	get yes/no parameter
91 **/
92
93const struct cvntab	Yntab[] =
94{
95	{ "y",	"es",	(cmdfun)1,	1 },
96	{ "n",	"o",	(cmdfun)0,	0 },
97	{ NULL,	NULL,	NULL,		0 }
98};
99
100int
101getynpar(const char *s)
102{
103	const struct cvntab	*r;
104
105	r = getcodpar(s, Yntab);
106	return (r->value2);
107}
108
109
110/**
111 **	get coded parameter
112 **/
113
114const struct cvntab *
115getcodpar(const char *s, const struct cvntab tab[])
116{
117	char				input[100];
118	const struct cvntab		*r;
119	int				flag;
120	const char			*p, *q;
121	int				c;
122	int				f;
123
124	flag = 0;
125	while (1)
126	{
127		flag |= (f = testnl());
128		if (flag)
129			printf("%s: ", s);
130		if (f)
131			getchar();		/* throw out the newline */
132		scanf("%*[ \t;]");
133		if ((c = scanf("%99[^ \t;\n]", input)) < 0)
134			exit(1);
135		if (c == 0)
136			continue;
137		flag = 1;
138
139		/* if command list, print four per line */
140		if (input[0] == '?' && input[1] == 0)
141		{
142			c = 4;
143			for (r = tab; r->abrev; r++)
144			{
145				strlcpy(input, r->abrev, sizeof input);
146				strlcat(input, r->full, sizeof input);
147				printf("%14.14s", input);
148				if (--c > 0)
149					continue;
150				c = 4;
151				printf("\n");
152			}
153			if (c != 4)
154				printf("\n");
155			continue;
156		}
157
158		/* search for in table */
159		for (r = tab; r->abrev; r++)
160		{
161			p = input;
162			for (q = r->abrev; *q; q++)
163				if (*p++ != *q)
164					break;
165			if (!*q)
166			{
167				for (q = r->full; *p && *q; q++, p++)
168					if (*p != *q)
169						break;
170				if (!*p || !*q)
171					break;
172			}
173		}
174
175		/* check for not found */
176		if (!r->abrev)
177		{
178			printf("invalid input; ? for valid inputs\n");
179			skiptonl(0);
180		}
181		else
182			return (r);
183	}
184}
185
186
187/**
188 **	get string parameter
189 **/
190
191void
192getstrpar(const char *s, char *r, int l, const char *t)
193{
194	int	i, f;
195	char	format[20];
196
197	if (t == 0)
198		t = " \t\n;";
199	(void)snprintf(format, sizeof format, "%%%d[^%s]", l, t);
200	while (1)
201	{
202		if ((f = testnl()) && s)
203			printf("%s: ", s);
204		if (f)
205			getchar();
206		scanf("%*[\t ;]");
207		i = scanf(format, r);
208		if (i < 0)
209			exit(1);
210		if (i != 0)
211			return;
212	}
213}
214
215
216/**
217 **	test if newline is next valid character
218 **/
219
220int
221testnl(void)
222{
223	int	c;
224
225	while ((c = getchar()) != '\n')
226		if ((c >= '0' && c <= '9') || c == '.' || c == '!' ||
227				(c >= 'A' && c <= 'Z') ||
228				(c >= 'a' && c <= 'z') || c == '-' || c == EOF)
229		{
230			ungetc(c, stdin);
231			return(0);
232		}
233	ungetc(c, stdin);
234	return (1);
235}
236
237
238/**
239 **	scan for newline
240 **/
241
242void
243skiptonl(int c)
244{
245	while (c != '\n')
246		if (!(c = getchar()))
247			return;
248	ungetc('\n', stdin);
249	return;
250}
251
252
253/**
254 **	test for valid terminator
255 **/
256
257static int
258testterm(void)
259{
260	int	c;
261
262	if (!(c = getchar()))
263		return (1);
264	if (c == '.')
265		return (0);
266	if (c == '\n' || c == ';')
267		ungetc(c, stdin);
268	return (1);
269}
270
271
272/*
273**  TEST FOR SPECIFIED DELIMETER
274**
275**	The standard input is scanned for the parameter.  If found,
276**	it is thrown away and non-zero is returned.  If not found,
277**	zero is returned.
278*/
279
280int
281readdelim(int d)
282{
283	int	c;
284
285	while ((c = getchar()))
286	{
287		if (c == d)
288			return (1);
289		if (c == ' ')
290			continue;
291		ungetc(c, stdin);
292		break;
293	}
294	return (0);
295}
296