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