4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 /* All Rights Reserved */
26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
34 #include <sys/types.h>
39 static int fmtcheck(char *);
42 #define PROMPT "Enter the date"
43 #define MESG "Please enter a date"
44 #define DEFAULT "%m/%d/%y"
46 static char *p_ndigit(char *, int *, int);
47 static char *p_date(char *, int, int, int);
48 static char *p_eday(char *, int, int);
49 static char *p_dlm(char *, char);
59 * All digits are valid for a YY year format
60 * 70-99 refer to the 20th Century
61 * 00-69 refer to the 21st Century
74 setmsg(char *msg
, char *fmt
, size_t sz
)
76 if ((fmt
== NULL
) || strcmp(fmt
, "%D") == 0)
78 (void) snprintf(msg
, sz
, "%s. Format is <%s>.", MESG
, fmt
);
82 p_ndigit(char *string
, int *value
, int n
)
89 for (ptr
= string
; *ptr
&& n
> 0; n
--, ptr
++) {
90 if (! isdigit((unsigned char)*ptr
))
92 accum
= (10 * accum
) + (*ptr
- '0');
101 p_date(char *string
, int llim
, int ulim
, int ndig
)
106 if (!(ptr
= p_ndigit(string
, &begin
, ndig
)))
108 if (begin
>= llim
&& begin
<= ulim
)
115 p_eday(char *string
, int llim
, int ulim
)
124 if (*string
== BLANK
) {
129 while (isdigit((unsigned char)*copy
) && (iday
< idaymax
)) {
130 daynum
[iday
] = *copy
++;
137 } else if (iday
== 2) {
144 if (!(ptr
= p_ndigit(string
, &begin
, iday
)))
147 if (begin
>= llim
&& begin
<= ulim
)
153 /* p_month will parse the string for the month - abbr. form i.e. JAN - DEC */
156 p_month(char *string
, char mnabr
)
158 static char *fmonth
[] = {
159 "JANUARY", "FEBRUARY", "MARCH", "APRIL",
160 "MAY", "JUNE", "JULY", "AUGUST",
161 "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
163 static char *amonth
[] = {
164 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
165 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
178 for (icnt
= 0; icnt
< 12; icnt
++)
179 mnth
[icnt
] = amonth
[icnt
];
182 for (icnt
= 0; icnt
< 12; icnt
++)
183 mnth
[icnt
] = fmonth
[icnt
];
188 while (((islower((unsigned char)*copy
)) ||
189 (isupper((unsigned char)*copy
))) && (imnth
< mlen
)) {
190 mletter
[imnth
] = toupper((unsigned char)*copy
++);
193 mletter
[imnth
] = '\0';
194 while (!(legit
) && (n
< 12)) {
195 if (strncmp(mletter
, mnth
[n
],
196 (imnth
= (int)strlen(mnth
[n
]))) == 0)
197 legit
= 1; /* found legitimate string */
201 for (ichng
= 0; ichng
< imnth
; ichng
++) {
202 *string
= toupper((unsigned char)*string
);
208 * I know this causes side effects, but it's less
209 * code than adding in a copy for string and using that
216 p_dlm(char *string
, char dchoice
)
223 (void) sscanf(string
, "%1c", &dlm
);
225 return (((dlm
== DELIM1
) || (dlm
== DELIM2
)) ? string
+1 : NULL
);
227 return ((dlm
== dchoice
) ? string
+ 1 : NULL
);
231 ckdate_err(char *fmt
, char *error
)
233 char defmesg
[MSGSIZ
];
235 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
237 setmsg(defmesg
, fmt
, MSGSIZ
);
238 puterror(stdout
, defmesg
, error
);
243 ckdate_hlp(char *fmt
, char *help
)
245 char defmesg
[MSGSIZ
];
247 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
249 setmsg(defmesg
, fmt
, MSGSIZ
);
250 puthelp(stdout
, defmesg
, help
);
255 * A little state machine that checks out the format to
256 * make sure it is acceptable.
267 case '%': /* previous state must be start or letter */
273 case 'd': /* previous state must be "%" */
287 case TAB
: /* previous state must be start or letter */
302 ckdate_val(char *fmt
, char *input
)
305 int valid
= 1; /* time of day string is valid for format */
307 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
313 while (*fmt
&& valid
) {
318 input
= p_date(input
, LD
, UD
, STDIG
);
324 input
= p_eday(input
, LD2
, UD
);
330 input
= p_date(input
, LM
, UM
, STDIG
);
336 input
= p_date(input
, LY
, UY
, STDIG
);
342 input
= p_date(input
, LCY
, UCY
, CCYY
);
348 input
= p_date(input
, LM
, UM
, STDIG
);
353 input
= p_dlm(input
, DELIM1
);
358 input
= p_date(input
, LD
, UD
, STDIG
);
363 input
= p_dlm(input
, DELIM1
);
368 input
= p_date(input
, LY
, UY
, STDIG
);
375 input
= p_month(input
, 'a');
381 input
= p_month(input
, 'f');
387 (void) sscanf(input
, "%1c", <rl
);
392 (void) sscanf(input
, "%1c", &dfl
);
396 } /* end of while fmt and valid */
398 if ((*fmt
== '\0') && ((input
!= NULL
) && *input
!= '\0')) {
402 return ((valid
== 0));
406 ckdate(char *date
, char *fmt
, char *defstr
, char *error
, char *help
,
409 char defmesg
[MSGSIZ
];
410 char input
[MAX_INPUT
];
416 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
419 setmsg(defmesg
, fmt
, MSGSIZ
);
420 (void) sprintf(ept
, "[?,q]");
426 putprmpt(stderr
, prompt
, NULL
, defstr
);
430 if (!strlen(input
)) {
432 (void) strcpy(date
, defstr
);
435 puterror(stderr
, defmesg
, error
);
437 } else if (strcmp(input
, "?") == 0) {
438 puthelp(stderr
, defmesg
, help
);
440 } else if (ckquit
&& strcmp(input
, "q") == 0) {
442 } else if (ckdate_val(fmt
, input
)) {
443 puterror(stderr
, defmesg
, error
);
446 (void) strcpy(date
, input
);