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