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
)
122 if (*string
== BLANK
) {
127 while (isdigit((unsigned char)*copy
) && (iday
< idaymax
)) {
134 } else if (iday
== 2) {
141 if (!(ptr
= p_ndigit(string
, &begin
, iday
)))
144 if (begin
>= llim
&& begin
<= ulim
)
150 /* p_month will parse the string for the month - abbr. form i.e. JAN - DEC */
153 p_month(char *string
, char mnabr
)
155 static char *fmonth
[] = {
156 "JANUARY", "FEBRUARY", "MARCH", "APRIL",
157 "MAY", "JUNE", "JULY", "AUGUST",
158 "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
160 static char *amonth
[] = {
161 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
162 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
175 for (icnt
= 0; icnt
< 12; icnt
++)
176 mnth
[icnt
] = amonth
[icnt
];
179 for (icnt
= 0; icnt
< 12; icnt
++)
180 mnth
[icnt
] = fmonth
[icnt
];
185 while (((islower((unsigned char)*copy
)) ||
186 (isupper((unsigned char)*copy
))) && (imnth
< mlen
)) {
187 mletter
[imnth
] = toupper((unsigned char)*copy
++);
190 mletter
[imnth
] = '\0';
191 while (!(legit
) && (n
< 12)) {
192 if (strncmp(mletter
, mnth
[n
],
193 (imnth
= (int)strlen(mnth
[n
]))) == 0)
194 legit
= 1; /* found legitimate string */
198 for (ichng
= 0; ichng
< imnth
; ichng
++) {
199 *string
= toupper((unsigned char)*string
);
205 * I know this causes side effects, but it's less
206 * code than adding in a copy for string and using that
213 p_dlm(char *string
, char dchoice
)
220 (void) sscanf(string
, "%1c", &dlm
);
222 return (((dlm
== DELIM1
) || (dlm
== DELIM2
)) ? string
+1 : NULL
);
224 return ((dlm
== dchoice
) ? string
+ 1 : NULL
);
228 ckdate_err(char *fmt
, char *error
)
230 char defmesg
[MSGSIZ
];
232 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
234 setmsg(defmesg
, fmt
, MSGSIZ
);
235 puterror(stdout
, defmesg
, error
);
240 ckdate_hlp(char *fmt
, char *help
)
242 char defmesg
[MSGSIZ
];
244 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
246 setmsg(defmesg
, fmt
, MSGSIZ
);
247 puthelp(stdout
, defmesg
, help
);
252 * A little state machine that checks out the format to
253 * make sure it is acceptable.
264 case '%': /* previous state must be start or letter */
270 case 'd': /* previous state must be "%" */
284 case TAB
: /* previous state must be start or letter */
299 ckdate_val(char *fmt
, char *input
)
302 int valid
= 1; /* time of day string is valid for format */
304 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
310 while (*fmt
&& valid
) {
315 input
= p_date(input
, LD
, UD
, STDIG
);
321 input
= p_eday(input
, LD2
, UD
);
327 input
= p_date(input
, LM
, UM
, STDIG
);
333 input
= p_date(input
, LY
, UY
, STDIG
);
339 input
= p_date(input
, LCY
, UCY
, CCYY
);
345 input
= p_date(input
, LM
, UM
, STDIG
);
350 input
= p_dlm(input
, DELIM1
);
355 input
= p_date(input
, LD
, UD
, STDIG
);
360 input
= p_dlm(input
, DELIM1
);
365 input
= p_date(input
, LY
, UY
, STDIG
);
372 input
= p_month(input
, 'a');
378 input
= p_month(input
, 'f');
384 (void) sscanf(input
, "%1c", <rl
);
389 (void) sscanf(input
, "%1c", &dfl
);
393 } /* end of while fmt and valid */
395 if ((*fmt
== '\0') && ((input
!= NULL
) && *input
!= '\0')) {
399 return ((valid
== 0));
403 ckdate(char *date
, char *fmt
, char *defstr
, char *error
, char *help
,
406 char defmesg
[MSGSIZ
];
407 char input
[MAX_INPUT
];
413 if ((fmt
!= NULL
) && (fmtcheck(fmt
) == 1))
416 setmsg(defmesg
, fmt
, MSGSIZ
);
417 (void) sprintf(ept
, "[?,q]");
423 putprmpt(stderr
, prompt
, NULL
, defstr
);
427 if (!strlen(input
)) {
429 (void) strcpy(date
, defstr
);
432 puterror(stderr
, defmesg
, error
);
434 } else if (strcmp(input
, "?") == 0) {
435 puthelp(stderr
, defmesg
, help
);
437 } else if (ckquit
&& strcmp(input
, "q") == 0) {
439 } else if (ckdate_val(fmt
, input
)) {
440 puterror(stderr
, defmesg
, error
);
443 (void) strcpy(date
, input
);