summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadm/common/ckdate.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libadm/common/ckdate.c
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libadm/common/ckdate.c')
-rw-r--r--usr/src/lib/libadm/common/ckdate.c451
1 files changed, 451 insertions, 0 deletions
diff --git a/usr/src/lib/libadm/common/ckdate.c b/usr/src/lib/libadm/common/ckdate.c
new file mode 100644
index 0000000000..e2b987990e
--- /dev/null
+++ b/usr/src/lib/libadm/common/ckdate.c
@@ -0,0 +1,451 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1997,1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*LINTLIBRARY*/
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "libadm.h"
+
+static int fmtcheck(char *);
+
+#define MSGSIZ 64
+#define PROMPT "Enter the date"
+#define MESG "Please enter a date"
+#define DEFAULT "%m/%d/%y"
+
+static char *p_ndigit(char *, int *, int);
+static char *p_date(char *, int, int, int);
+static char *p_eday(char *, int, int);
+static char *p_dlm(char *, char);
+
+#define MLIM 9
+#define STDIG 2
+#define LD2 10
+#define LD 01
+#define UD 31
+#define LM 01
+#define UM 12
+/*
+ * All digits are valid for a YY year format
+ * 70-99 refer to the 20th Century
+ * 00-69 refer to the 21st Century
+ */
+#define LY 00
+#define UY 99
+#define LCY 1970
+#define UCY 9999
+#define CCYY 4
+#define DELIM1 '/'
+#define DELIM2 '-'
+#define BLANK ' '
+#define TAB ' '
+
+static void
+setmsg(char *msg, char *fmt)
+{
+ if ((fmt == NULL) || strcmp(fmt, "%D") == 0)
+ fmt = "%m/%d/%y";
+ (void) sprintf(msg, "%s. Format is <%s>.", MESG, fmt);
+}
+
+static char *
+p_ndigit(char *string, int *value, int n)
+{
+ char *ptr;
+ int accum = 0;
+
+ if (!string)
+ return (NULL);
+ for (ptr = string; *ptr && n > 0; n--, ptr++) {
+ if (! isdigit((unsigned char)*ptr))
+ return (NULL);
+ accum = (10 * accum) + (*ptr - '0');
+ }
+ if (n)
+ return (NULL);
+ *value = accum;
+ return (ptr);
+}
+
+static char *
+p_date(char *string, int llim, int ulim, int ndig)
+{
+ char *ptr;
+ int begin = -1;
+
+ if (!(ptr = p_ndigit(string, &begin, ndig)))
+ return (NULL);
+ if (begin >= llim && begin <= ulim)
+ return (ptr);
+ else
+ return (NULL);
+}
+
+static char *
+p_eday(char *string, int llim, int ulim)
+{
+ char *ptr, *copy;
+ char daynum[3];
+ int begin = -1;
+ int iday = 0;
+ int idaymax = 2;
+
+ daynum[0] = '\0';
+ if (*string == BLANK) {
+ string++;
+ idaymax--;
+ }
+ copy = string;
+ while (isdigit((unsigned char)*copy) && (iday < idaymax)) {
+ daynum[iday] = *copy++;
+ iday++;
+ }
+ daynum[iday] = '\0';
+ if (iday == 1) {
+ llim = 1;
+ ulim = 9;
+ } else if (iday == 2) {
+ llim = 10;
+ ulim = 31;
+ }
+ if (iday == 0)
+ return (NULL);
+
+ if (!(ptr = p_ndigit(string, &begin, iday)))
+ return (NULL);
+
+ if (begin >= llim && begin <= ulim)
+ return (ptr);
+ else
+ return (NULL);
+}
+
+/* p_month will parse the string for the month - abbr. form i.e. JAN - DEC */
+
+static char *
+p_month(char *string, char mnabr)
+{
+ static char *fmonth[] = {
+ "JANUARY", "FEBRUARY", "MARCH", "APRIL",
+ "MAY", "JUNE", "JULY", "AUGUST",
+ "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
+ };
+ static char *amonth[] = {
+ "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
+ "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
+ };
+ int ichng, icnt;
+ char *mnth[12];
+ char *copy;
+ char mletter[MLIM];
+ int mlen;
+ int imnth = 0;
+ int legit = 0;
+ int n = 0;
+
+ if (mnabr == 'a') {
+ mlen = 3;
+ for (icnt = 0; icnt < 12; icnt++)
+ mnth[icnt] = amonth[icnt];
+ } else {
+ mlen = 9;
+ for (icnt = 0; icnt < 12; icnt++)
+ mnth[icnt] = fmonth[icnt];
+ }
+
+ copy = string;
+
+ while (((islower((unsigned char)*copy)) ||
+ (isupper((unsigned char)*copy))) && (imnth < mlen)) {
+ mletter[imnth] = toupper((unsigned char)*copy++);
+ imnth++;
+ }
+ mletter[imnth] = '\0';
+ while (!(legit) && (n < 12)) {
+ if (strncmp(mletter, mnth[n],
+ (imnth = (int)strlen(mnth[n]))) == 0)
+ legit = 1; /* found legitimate string */
+ n++;
+ }
+ if (legit) {
+ for (ichng = 0; ichng < imnth; ichng++) {
+ *string = toupper((unsigned char)*string);
+ string++;
+ }
+
+ return (string);
+ /*
+ * I know this causes side effects, but it's less
+ * code than adding in a copy for string and using that
+ */
+ } else
+ return (NULL);
+}
+
+static char *
+p_dlm(char *string, char dchoice)
+{
+ char dlm;
+
+
+ if (! string)
+ return (NULL);
+ (void) sscanf(string, "%1c", &dlm);
+ if (dchoice == '/')
+ return (((dlm == DELIM1) || (dlm == DELIM2)) ? string+1 : NULL);
+ else
+ return ((dlm == dchoice) ? string + 1 : NULL);
+}
+
+int
+ckdate_err(char *fmt, char *error)
+{
+ char defmesg[MSGSIZ];
+
+ if ((fmt != NULL) && (fmtcheck(fmt) == 1))
+ return (4);
+ setmsg(defmesg, fmt);
+ puterror(stdout, defmesg, error);
+ return (0);
+}
+
+int
+ckdate_hlp(char *fmt, char *help)
+{
+ char defmesg[MSGSIZ];
+
+ if ((fmt != NULL) && (fmtcheck(fmt) == 1))
+ return (4);
+ setmsg(defmesg, fmt);
+ puthelp(stdout, defmesg, help);
+ return (0);
+}
+
+/*
+ * A little state machine that checks out the format to
+ * make sure it is acceptable.
+ * return value 1: NG
+ * return value 0: OK
+ */
+static int
+fmtcheck(char *fmt)
+{
+ int percent = 0;
+
+ while (*fmt) {
+ switch (*fmt++) {
+ case '%': /* previous state must be start or letter */
+ if (percent == 0)
+ percent = 1;
+ else
+ return (1);
+ break;
+ case 'd': /* previous state must be "%" */
+ case 'e':
+ case 'm':
+ case 'y':
+ case 'Y':
+ case 'D':
+ case 'h':
+ case 'b':
+ case 'B':
+ if (percent == 1)
+ percent = 0;
+ else
+ return (1);
+ break;
+ case TAB: /* previous state must be start or letter */
+ case BLANK:
+ case DELIM1:
+ case DELIM2:
+ if (percent == 1)
+ return (1);
+ break;
+ default:
+ return (1);
+ }
+ }
+ return (percent);
+}
+
+int
+ckdate_val(char *fmt, char *input)
+{
+ char ltrl, dfl;
+ int valid = 1; /* time of day string is valid for format */
+
+ if ((fmt != NULL) && (fmtcheck(fmt) == 1))
+ return (4);
+
+ if (fmt == NULL)
+ fmt = DEFAULT;
+ ltrl = '\0';
+ while (*fmt && valid) {
+ if ((*fmt) == '%') {
+ fmt++;
+ switch (*fmt) {
+ case 'd':
+ input = p_date(input, LD, UD, STDIG);
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'e':
+ input = p_eday(input, LD2, UD);
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'm':
+ input = p_date(input, LM, UM, STDIG);
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'y':
+ input = p_date(input, LY, UY, STDIG);
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'Y':
+ input = p_date(input, LCY, UCY, CCYY);
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'D':
+ input = p_date(input, LM, UM, STDIG);
+ if (!input) {
+ valid = 0;
+ break;
+ }
+ input = p_dlm(input, DELIM1);
+ if (!input) {
+ valid = 0;
+ break;
+ }
+ input = p_date(input, LD, UD, STDIG);
+ if (!input) {
+ valid = 0;
+ break;
+ }
+ input = p_dlm(input, DELIM1);
+ if (!input) {
+ valid = 0;
+ break;
+ }
+ input = p_date(input, LY, UY, STDIG);
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'h':
+ case 'b':
+ input = p_month(input, 'a');
+ if (!input)
+ valid = 0;
+ break;
+
+ case 'B':
+ input = p_month(input, 'f');
+ if (!input)
+ valid = 0;
+ break;
+
+ default:
+ (void) sscanf(input, "%1c", &ltrl);
+ input++;
+ }
+ } else {
+ dfl = '\0';
+ (void) sscanf(input, "%1c", &dfl);
+ input++;
+ }
+ fmt++;
+ } /* end of while fmt and valid */
+
+ if ((*fmt == NULL) && ((input != NULL) && *input != 0)) {
+ if (*input != NULL)
+ valid = 0;
+ }
+ return ((valid == 0));
+}
+
+int
+ckdate(char *date, char *fmt, char *defstr, char *error, char *help,
+ char *prompt)
+{
+ char defmesg[MSGSIZ];
+ char input[MAX_INPUT];
+ char *ept, end[128];
+
+ ept = end;
+ *ept = '\0';
+
+ if ((fmt != NULL) && (fmtcheck(fmt) == 1))
+ return (4);
+
+ setmsg(defmesg, fmt);
+ (void) sprintf(ept, "[?,q]");
+
+ if (!prompt)
+ prompt = PROMPT;
+
+start:
+ putprmpt(stderr, prompt, NULL, defstr);
+ if (getinput(input))
+ return (1);
+
+ if (!strlen(input)) {
+ if (defstr) {
+ (void) strcpy(date, defstr);
+ return (0);
+ }
+ puterror(stderr, defmesg, error);
+ goto start;
+ } else if (strcmp(input, "?") == 0) {
+ puthelp(stderr, defmesg, help);
+ goto start;
+ } else if (ckquit && strcmp(input, "q") == 0) {
+ return (3);
+ } else if (ckdate_val(fmt, input)) {
+ puterror(stderr, defmesg, error);
+ goto start;
+ }
+ (void) strcpy(date, input);
+ return (0);
+}