1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
24
25
26 /*
27 * Copyright (c) 1997,1998 by Sun Microsystems, Inc.
28 * All rights reserved.
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32 /*LINTLIBRARY*/
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <limits.h>
38 #include <sys/types.h>
39 #include <stdlib.h>
40 #include "libadm.h"
41
42 static int fmtcheck(char *);
43
44 #define PROMPT "Enter the time of day"
45 #define ERRMSG "Please enter the time of day. Format is"
46 #define DEFAULT "%H:%M"
47
48 #define TLEN 3
49 #define LH 00
50 #define UH 23
51 #define USH 12
52 #define LM 00
53 #define UM 59
54 #define LS 00
55 #define US 59
56 #define DELIM1 ':'
57 #define BLANK ' '
58 #define TAB ' '
59
60 static void
setmsg(char * msg,char * fmt)61 setmsg(char *msg, char *fmt)
62 {
63 if (fmt == NULL)
64 fmt = DEFAULT;
65 (void) sprintf(msg, "%s <%s>.", ERRMSG, fmt);
66 }
67
68 static char *
p_ndig(char * string,int * value)69 p_ndig(char *string, int *value)
70 {
71 char *ptr;
72 int accum = 0;
73 int n = 2;
74
75 if (!string)
76 return (0);
77 for (ptr = string; *ptr && n > 0; n--, ptr++) {
78 if (! isdigit((unsigned char)*ptr))
79 return (NULL);
80 accum = (10 * accum) + (*ptr - '0');
81 }
82 if (n)
83 return (NULL);
84 *value = accum;
85 return (ptr);
86 }
87
88 static char *
p_time(char * string,int llim,int ulim)89 p_time(char *string, int llim, int ulim)
90 {
91 char *ptr;
92 int begin = -1;
93 if (!(ptr = p_ndig(string, &begin)))
94 return (NULL);
95 if (begin >= llim && begin <= ulim)
96 return (ptr);
97 else return (NULL);
98 }
99
100 /* p_meridian will parse the string for the meridian - AM/PM or am/pm */
101
102 static char *
p_meridian(char * string)103 p_meridian(char *string)
104 {
105 static char *middle[] = { "AM", "PM", "am", "pm" };
106 int legit, n;
107 char mid[TLEN];
108
109 legit = 0;
110 n = 0;
111 mid[2] = '\0';
112 (void) sscanf(string, "%2s", mid);
113 while (!(legit) && (n < 4)) {
114 if ((strncmp(mid, middle[n], 2)) == 0)
115 legit = 1; /* found legitimate string */
116 n++;
117 }
118 if (legit)
119 return (string+2);
120 return (NULL);
121 }
122
123 static char *
p_delim(char * string,char dchoice)124 p_delim(char *string, char dchoice)
125 {
126 char dlm;
127
128 if (! string)
129 return (NULL);
130 (void) sscanf(string, "%1c", &dlm);
131 return ((dlm == dchoice) ? string + 1 : NULL);
132 }
133
134 int
cktime_val(char * fmt,char * input)135 cktime_val(char *fmt, char *input)
136 {
137 char ltrl, dfl;
138 int valid = 1; /* time of day string is valid for format */
139
140 if ((fmt != NULL) && (fmtcheck(fmt) == 1))
141 return (4);
142
143 if (fmt == NULL)
144 fmt = DEFAULT;
145 ltrl = '\0';
146 while (*fmt && valid) {
147 if ((*fmt) == '%') {
148 switch (*++fmt) {
149 case 'H':
150 input = p_time(input, LH, UH);
151 if (!input)
152 valid = 0;
153 break;
154
155 case 'M':
156 input = p_time(input, LM, UM);
157 if (!input)
158 valid = 0;
159 break;
160
161 case 'S':
162 input = p_time(input, LS, US);
163 if (!input)
164 valid = 0;
165 break;
166
167 case 'T':
168 input = p_time(input, LH, UH);
169 if (!input) {
170 valid = 0;
171 break;
172 }
173
174 input = p_delim(input, DELIM1);
175 if (!input) {
176 valid = 0;
177 break;
178 }
179 input = p_time(input, LM, UM);
180 if (!input) {
181 valid = 0;
182 break;
183 }
184 input = p_delim(input, DELIM1);
185 if (!input) {
186 valid = 0;
187 break;
188 }
189 input = p_time(input, LS, US);
190 if (!input)
191 valid = 0;
192 break;
193
194 case 'R':
195 input = p_time(input, LH, UH);
196 if (!input) {
197 valid = 0;
198 break;
199 }
200 input = p_delim(input, DELIM1);
201 if (!input) {
202 valid = 0;
203 break;
204 }
205 input = p_time(input, LM, UM);
206 if (!input) {
207 valid = 0;
208 break;
209 }
210 break;
211
212 case 'r':
213 input = p_time(input, LH, USH);
214 if (!input) {
215 valid = 0;
216 break;
217 }
218 input = p_delim(input, DELIM1);
219 if (!input) {
220 valid = 0;
221 break;
222 }
223 input = p_time(input, LM, UM);
224 if (!input) {
225 valid = 0;
226 break;
227 }
228 input = p_delim(input, DELIM1);
229 if (!input) {
230 valid = 0;
231 break;
232 }
233 input = p_time(input, LS, US);
234 if (!input) {
235 valid = 0;
236 break;
237 }
238 input = p_delim(input, BLANK);
239 if (!input) {
240 valid = 0;
241 break;
242 }
243 input = p_meridian(input);
244 if (!input)
245 valid = 0;
246 break;
247
248 case 'I':
249 input = p_time(input, LH, USH);
250 if (!input)
251 valid = 0;
252 break;
253
254 case 'p':
255 input = p_meridian(input);
256 if (!input)
257 valid = 0;
258 break;
259
260 default:
261 (void) sscanf(input++, "%1c", <rl);
262 }
263 } else {
264 dfl = '\0';
265 (void) sscanf(input, "%1c", &dfl);
266 input++;
267 }
268 fmt++;
269 }
270
271 if (!(*fmt) && (input) && (*input))
272 valid = 0;
273
274 return ((valid == 0));
275 }
276
277 int
cktime_err(char * fmt,char * error)278 cktime_err(char *fmt, char *error)
279 {
280 char defmesg[128];
281
282 if ((fmt != NULL) && (fmtcheck(fmt) == 1))
283 return (4);
284 setmsg(defmesg, fmt);
285 puterror(stdout, defmesg, error);
286 return (0);
287 }
288
289 int
cktime_hlp(char * fmt,char * help)290 cktime_hlp(char *fmt, char *help)
291 {
292 char defmesg[128];
293
294 if ((fmt != NULL) && (fmtcheck(fmt) == 1))
295 return (4);
296 setmsg(defmesg, fmt);
297 puthelp(stdout, defmesg, help);
298 return (0);
299 }
300
301 /*
302 * A little state machine that checks out the format to
303 * make sure it is acceptable.
304 * return value 1: NG
305 * return value 0: OK
306 */
307 int
fmtcheck(char * fmt)308 fmtcheck(char *fmt)
309 {
310 int percent = 0;
311
312 while (*fmt) {
313 switch (*fmt++) {
314 case '%': /* previous state must be start or letter */
315 if (percent == 0)
316 percent = 1;
317 else
318 return (1);
319 break;
320 case 'H': /* previous state must be "%" */
321 case 'M':
322 case 'S':
323 case 'T':
324 case 'R':
325 case 'r':
326 case 'I':
327 case 'p':
328 if (percent == 1)
329 percent = 0;
330 else
331 return (1);
332 break;
333 case TAB: /* previous state must be start or letter */
334 case BLANK:
335 case DELIM1:
336 if (percent == 1)
337 return (1);
338 break;
339 default:
340 return (1);
341 }
342 }
343 return (percent);
344 }
345
346 int
cktime(char * tod,char * fmt,char * defstr,char * error,char * help,char * prompt)347 cktime(char *tod, char *fmt, char *defstr, char *error, char *help,
348 char *prompt)
349 {
350 char input[MAX_INPUT],
351 defmesg[128];
352
353 if ((fmt != NULL) && (fmtcheck(fmt) == 1))
354 return (4);
355
356 if (fmt == NULL)
357 fmt = DEFAULT;
358 setmsg(defmesg, fmt);
359 if (!prompt)
360 prompt = "Enter a time of day";
361
362 start:
363 putprmpt(stderr, prompt, NULL, defstr);
364 if (getinput(input))
365 return (1);
366
367 if (!strlen(input)) {
368 if (defstr) {
369 (void) strcpy(tod, defstr);
370 return (0);
371 }
372 puterror(stderr, defmesg, error);
373 goto start;
374 }
375 if (strcmp(input, "?") == 0) {
376 puthelp(stderr, defmesg, help);
377 goto start;
378 }
379 if (ckquit && (strcmp(input, "q") == 0))
380 return (3);
381
382 if (cktime_val(fmt, input)) {
383 puterror(stderr, defmesg, error);
384 goto start;
385 }
386 (void) strcpy(tod, input);
387 return (0);
388 }
389