1 /* @(#)io.c	1.28 09/07/28 Copyright 1988-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)io.c	1.28 09/07/28 Copyright 1988-2009 J. Schilling";
6 #endif
7 /*
8  *	Copyright (c) 1988-2009 J. Schilling
9  */
10 /*
11  * The contents of this file are subject to the terms of the
12  * Common Development and Distribution License, Version 1.0 only
13  * (the "License").  You may not use this file except in compliance
14  * with the License.
15  *
16  * See the file CDDL.Schily.txt in this distribution for details.
17  * A copy of the CDDL is also available via the Internet at
18  * http://www.opensource.org/licenses/cddl1.txt
19  *
20  * When distributing Covered Code, include this CDDL HEADER in each
21  * file and include the License file CDDL.Schily.txt from this distribution.
22  */
23 
24 #include <schily/stdio.h>
25 #include <schily/standard.h>
26 #include <schily/varargs.h>
27 #include <schily/stdlib.h>
28 #include <schily/string.h>
29 #include <schily/utypes.h>
30 #include <schily/schily.h>
31 #include <schily/ctype.h>
32 
33 #include "fmt.h"
34 
35 LOCAL BOOL	cvt_blocks __PR((char *, long *, long, long, struct disk *));
36 LOCAL void	prt_std	   __PR((char *, long, long, long, struct disk *));
37 LOCAL void	prt_blocks __PR((char *, long, long, long, struct disk *));
38 
39 EXPORT char *
skipwhite(s)40 skipwhite(s)
41 		const char	*s;
42 {
43 	register const Uchar	*p = (const Uchar *)s;
44 
45 	while (*p) {
46 		if (!isspace(*p))
47 			break;
48 		p++;
49 	}
50 	return ((char *)p);
51 }
52 
53 /* ARGSUSED */
54 EXPORT BOOL
cvt_std(linep,lp,mini,maxi,dp)55 cvt_std(linep, lp, mini, maxi, dp)
56 	char	*linep;
57 	long	*lp;
58 	long	mini;
59 	long	maxi;
60 	struct disk	*dp;
61 {
62 	long	l	= -1L;
63 
64 /*	printf("cvt_std(\"%s\", %d, %d, %d);\n", linep, *lp, mini, maxi);*/
65 
66 	if (linep[0] == '?') {
67 		printf("Enter a number in the range from %ld to %ld\n",
68 								mini, maxi);
69 		printf("The default radix is 10\n");
70 		printf("Precede number with '0x' for hexadecimal or with '0' for octal\n");
71 		printf("Shorthands are:\n");
72 		printf("\t'^' for minimum value (%ld)\n", mini);
73 		printf("\t'$' for maximum value (%ld)\n", maxi);
74 		printf("\t'+' for incrementing value to %ld\n", *lp + 1);
75 		printf("\t'-' for decrementing value to %ld\n", *lp - 1);
76 		return (FALSE);
77 	}
78 	if (linep[0] == '^' && *skipwhite(&linep[1]) == '\0') {
79 		l = mini;
80 	} else if (linep[0] == '$' && *skipwhite(&linep[1]) == '\0') {
81 		l = maxi;
82 	} else if (linep[0] == '+' && *skipwhite(&linep[1]) == '\0') {
83 		if (*lp < maxi)
84 			l = *lp + 1;
85 	} else if (linep[0] == '-' && *skipwhite(&linep[1]) == '\0') {
86 		if (*lp > mini)
87 			l = *lp - 1;
88 	} else if (*astol(linep, &l)) {
89 		printf("Not a number: '%s'.\n", linep);
90 		return (FALSE);
91 	}
92 	if (l < mini || l > maxi) {
93 		printf("'%s' is out of range.\n", linep);
94 		return (FALSE);
95 	}
96 	*lp = l;
97 	return (TRUE);
98 }
99 
100 LOCAL BOOL
cvt_blocks(linep,lp,mini,maxi,dp)101 cvt_blocks(linep, lp, mini, maxi, dp)
102 	char	*linep;
103 	long	*lp;
104 	long	mini;
105 	long	maxi;
106 	struct disk	*dp;
107 {
108 	long	l;
109 	long	cyls	= 0L;
110 	long	heads	= 0L;
111 	long	secs	= 0L;
112 	char	*hp;
113 	char	*sp;
114 
115 	if (linep[0] == '?') {
116 		printf("To enter blocks as simple block count:\n");
117 		(void) cvt_std(linep, lp, mini, maxi, dp);
118 		printf("\tNOTE: '$' will fill this partition to the end of the disk.\n");
119 		printf("To enter blocks as mega bytes:\n");
120 		printf("\tEnter size in megabytes as floating point number.\n");
121 		printf("\t(must be directly followed by 'm' or 'M' e.g. 12.5M)\n");
122 		printf("To enter blocks as cyls/tracks/sectors:\n");
123 		printf("\tEnter a number in the form cyls/tracks/secs or cyls/tracks or cyls/\n");
124 		(void) cvt_bcyls(linep, lp, mini, maxi, dp);
125 		return (FALSE);
126 	}
127 	/*
128 	 * If line contains no slash
129 	 * and no character which tells us to use megabytes
130 	 * convert as blocknumber.
131 	 */
132 	if (linep[0] != '>' &&
133 			!strchr(linep, '/') &&
134 			!strchr(linep, '.') &&
135 			!strchr(linep, 'm') && !strchr(linep, 'M'))
136 		return (cvt_std(linep, lp, mini, maxi, dp));
137 
138 	sp = hp = strchr(linep, '/');
139 	if (hp) {
140 		/*
141 		 * It's a cyl/track/sec notation.
142 		 */
143 		*hp++ = '\0';
144 		if (!(sp = strchr(hp, '/'))) {
145 			sp = &hp[-1];
146 		} else {
147 			*sp++ = '\0';
148 		}
149 
150 		if (linep[0] && !cvt_std(linep, &cyls, 0L, dp->lncyl, dp))
151 			return (FALSE);
152 		if (hp[0] && !cvt_std(hp, &heads, 0L, dp->lhead-1L, dp))
153 			return (FALSE);
154 		if (sp[0] && !cvt_std(sp, &secs, 0L, dp->lspt-1L, dp))
155 			return (FALSE);
156 
157 		l = secs + heads * dp->lspt +
158 			cyls * (dp->lhead * dp->lspt);
159 
160 		if (l < mini || l > maxi) {
161 			printf("'%ld' is out of range.\n", l);
162 			return (FALSE);
163 		}
164 	} else if (linep[0] == '>') {
165 		/*
166 		 * It's ---> reach to the next partition's beginning.
167 		 */
168 		return (cvt_bcyls(linep, lp, mini, maxi, dp));
169 	} else {
170 		int a;
171 		double d;
172 /*
173  * atof() should be in stdlib.h. If there is no stdlib.h, schily/stdlib.h has the def
174  */
175 /*		extern	double atof();*/
176 		/*
177 		 * It's megabytes
178 		 */
179 		d = atof(linep);
180 		d *= 2048.0;	/* Now we have 512 Byte sectors */
181 		l = d;
182 
183 		/*
184 		 * Round up to next cylinder.
185 		 */
186 		a = l / (dp->lhead * dp->lspt);
187 		if (l % (dp->lhead * dp->lspt)) {
188 			l = ++a * (dp->lhead * dp->lspt);
189 		}
190 	}
191 	*lp = l;
192 	return (TRUE);
193 }
194 
195 /* ARGSUSED */
196 LOCAL void
prt_std(s,l,mini,maxi,dp)197 prt_std(s, l, mini, maxi, dp)
198 	char	*s;
199 	long	l;
200 	long	mini;
201 	long	maxi;
202 	struct disk *dp;
203 {
204 	printf("%s %ld (%ld - %ld)/<cr>:", s, l, mini, maxi);
205 }
206 
207 LOCAL void
prt_blocks(s,l,mini,maxi,dp)208 prt_blocks(s, l, mini, maxi, dp)
209 	char	*s;
210 	long	l;
211 	long	mini;
212 	long	maxi;
213 	struct disk	*dp;
214 {
215 	long	cyl;
216 	long	head;
217 	long	sec;
218 
219 	cyl = l / (dp->lhead*dp->lspt);
220 	head = (l - (cyl * dp->lhead * dp->lspt)) / dp->lspt;
221 	sec = l - (cyl * dp->lhead * dp->lspt)
222 		- (head * dp->lspt);
223 
224 	printf("%s %ld, %ld/%ld/%ld (%ld - %ld)/<cr>:", s, l, cyl, head, sec,
225 								mini, maxi);
226 }
227 
228 EXPORT BOOL
getvalue(s,lp,mini,maxi,prt,cvt,dp)229 getvalue(s, lp, mini, maxi, prt, cvt, dp)
230 	char	*s;
231 	long	*lp;
232 	long	mini;
233 	long	maxi;
234 	void	(*prt) __PR((char *, long, long, long, struct disk *));
235 	BOOL	(*cvt) __PR((char *, long *, long, long, struct disk *));
236 	struct disk	*dp;
237 {
238 	char	line[128];
239 	char	*linep;
240 
241 	for (;;) {
242 		(*prt)(s, *lp, mini, maxi, dp);
243 		flush();
244 		line[0] = '\0';
245 		if (getline(line, 80) == EOF)
246 			exit(EX_BAD);
247 
248 		linep = skipwhite(line);
249 		/*
250 		 * Nicht initialisierte Variablen
251 		 * duerfen nicht uebernommen werden
252 		 */
253 		if (linep[0] == '\0' && *lp != -1L)
254 			return (FALSE);
255 
256 		if (strlen(linep) == 0) {
257 			/* Leere Eingabe */
258 		} else if ((*cvt)(linep, lp, mini, maxi, dp))
259 			return (TRUE);
260 	}
261 	/* NOTREACHED */
262 }
263 
264 EXPORT BOOL
getlong(s,lp,mini,maxi)265 getlong(s, lp, mini, maxi)
266 	char	*s;
267 	long	*lp;
268 	long	mini;
269 	long	maxi;
270 {
271 	return (getvalue(s, lp, mini, maxi, prt_std, cvt_std, (void *)0));
272 }
273 
274 EXPORT BOOL
getint(s,ip,mini,maxi)275 getint(s, ip, mini, maxi)
276 	char	*s;
277 	int	*ip;
278 	int	mini;
279 	int	maxi;
280 {
281 	long	l = *ip;
282 	BOOL	ret;
283 
284 	ret = getlong(s, &l, (long)mini, (long)maxi);
285 	*ip = l;
286 	return (ret);
287 }
288 
289 EXPORT BOOL
getdiskcyls(s,lp,mini,maxi)290 getdiskcyls(s, lp, mini, maxi)
291 	char	*s;
292 	long	*lp;
293 	long	mini;
294 	long	maxi;
295 {
296 	return (getvalue(s, lp, mini, maxi, prt_std, cvt_cyls, (void *)0));
297 }
298 
299 EXPORT BOOL
getdiskblocks(s,lp,mini,maxi,dp)300 getdiskblocks(s, lp, mini, maxi, dp)
301 	char	*s;
302 	long	*lp;
303 	long	mini;
304 	long	maxi;
305 	struct disk	*dp;
306 {
307 	return (getvalue(s, lp, mini, maxi, prt_blocks, cvt_blocks, dp));
308 }
309 
310 /* VARARGS1 */
311 EXPORT BOOL
312 #ifdef	PROTOTYPES
yes(char * form,...)313 yes(char *form, ...)
314 #else
315 yes(form, va_alist)
316 	char	*form;
317 	va_dcl
318 #endif
319 {
320 	va_list	args;
321 	char okbuf[10];
322 
323 again:
324 #ifdef	PROTOTYPES
325 	va_start(args, form);
326 #else
327 	va_start(args);
328 #endif
329 	printf("%r", form, args);
330 	va_end(args);
331 	flush();
332 	if (getline(okbuf, sizeof (okbuf)) == EOF)
333 		exit(EX_BAD);
334 	if (okbuf[0] == '?') {
335 		printf("Enter 'y', 'Y', 'yes' or 'YES' if you agree with the previous asked question.\n");
336 		printf("All other input will be handled as if the question has beed answered with 'no'.\n");
337 		goto again;
338 	}
339 	if (streql(okbuf, "y") || streql(okbuf, "yes") ||
340 	    streql(okbuf, "Y") || streql(okbuf, "YES"))
341 		return (TRUE);
342 	else
343 		return (FALSE);
344 }
345 
346 void
prbytes(s,cp,n)347 prbytes(s, cp, n)
348 		char		*s;
349 	register unsigned char	*cp;
350 	register int		n;
351 {
352 	printf("%s", s);
353 	while (--n >= 0)
354 		printf(" %02X", *cp++);
355 	printf("\n");
356 }
357 
358 EXPORT char *
permstring(s)359 permstring(s)
360 	const char	*s;
361 {
362 	char	*p;
363 
364 	if ((p = malloc(strlen(s)+1)) != NULL)
365 		strcpy(p, s);
366 	return (p);
367 }
368 
369 EXPORT struct strval *
strval(val,sp)370 strval(val, sp)
371 	int	val;
372 	struct strval *sp;
373 {
374 	while (sp->s_name) {
375 		if (val == sp->s_val)
376 			return (sp);
377 		sp++;
378 	}
379 	return ((struct strval *)0);
380 }
381 
382 EXPORT struct strval *
namestrval(name,sp)383 namestrval(name, sp)
384 	const char	*name;
385 	struct strval	*sp;
386 {
387 	while (sp->s_name) {
388 		if (strcmp(name, sp->s_name) == 0)
389 			return (sp);
390 		sp++;
391 	}
392 	return ((struct strval *)0);
393 }
394 
395 EXPORT BOOL
getstrval(s,lp,sp,deflt)396 getstrval(s, lp, sp, deflt)
397 	const char	*s;
398 	long		*lp;
399 	struct strval	*sp;
400 	long		deflt;
401 {
402 	struct strval *csp;
403 	char	line[128];
404 	char	*linep;
405 
406 	for (;;) {
407 		csp = strval(*lp, sp);
408 		printf("%s [%s]:", s, csp->s_name);
409 		flush();
410 		line[0] = '\0';
411 		if (getline(line, 80) == EOF)
412 			exit(EX_BAD);
413 
414 		linep = skipwhite(line);
415 		/*
416 		 * Nicht initialisierte Variablen
417 		 * duerfen nicht uebernommen werden
418 		 */
419 		if (linep[0] == '\0' && *lp != -1L)
420 			return (FALSE);
421 
422 		if (strlen(linep) == 0) {
423 			/* Leere Eingabe */
424 		} else if (streql(linep, "?") || streql(linep, "help")) {
425 			printf("Possible values are:\n");
426 			for (csp = sp; csp->s_name; csp++) {
427 				printf("%s\t%s\n", csp->s_name, csp->s_text);
428 			}
429 		} else if ((csp = namestrval(linep, sp)) != 0) {
430 			*lp = csp->s_val;
431 			return (TRUE);
432 		}
433 	}
434 	/* NOTREACHED */
435 }
436