summaryrefslogtreecommitdiff
path: root/usr/src/common/util/getresponse.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common/util/getresponse.c')
-rw-r--r--usr/src/common/util/getresponse.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/usr/src/common/util/getresponse.c b/usr/src/common/util/getresponse.c
new file mode 100644
index 0000000000..cc838a7ab1
--- /dev/null
+++ b/usr/src/common/util/getresponse.c
@@ -0,0 +1,186 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <regex.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <errno.h>
+#include "getresponse.h"
+
+/* defaults - C locale values for yesstr, nostr, yesexpr (LC_MESSAGES) */
+#define DEFAULT_YESSTR "yes"
+#define DEFAULT_NOSTR "no"
+#define DEFAULT_YESEXPR "^[yY]"
+#define DEFAULT_NOEXPR "^[nN]"
+
+#define FREE_MEM \
+ if (yesstr) \
+ free(yesstr); \
+ if (nostr) \
+ free(nostr); \
+ if (yesexpr) \
+ free(yesexpr); \
+ if (noexpr) \
+ free(noexpr)
+
+#define SET_DEFAULT_STRS \
+ yesstr = DEFAULT_YESSTR; \
+ nostr = DEFAULT_NOSTR; \
+ yesexpr = DEFAULT_YESEXPR; \
+ noexpr = DEFAULT_NOEXPR;
+
+/* variables used by getresponse functions */
+char *yesstr = NULL;
+char *nostr = NULL;
+
+/* for regcomp()/regexec() yesexpr and noexpr */
+static regex_t preg_yes, preg_no;
+
+/*
+ * This function compiles a regular expression that is used to match an
+ * affirmative response from the user, and also assigns the strings used
+ * in the prompts that request affirmative or negative responses. The
+ * locale's values for YESEXPR, NOEXPR, YESSTR and NOSTR are used.
+ *
+ * If there are any problems using the locale's YESEXPR, NOEXPR, YESSTR or NOSTR
+ * values, default values of YESEXPR, YESSTR and NOSTR will be used
+ * as a fallback. The default values are the same as the C locale values.
+ */
+int
+init_yes(void)
+{
+ int fallback = 0;
+ char *yesexpr;
+ char *noexpr;
+
+ /* get yes expression and strings for yes/no prompts */
+ yesstr = strdup(nl_langinfo(YESSTR));
+ nostr = strdup(nl_langinfo(NOSTR));
+ yesexpr = strdup(nl_langinfo(YESEXPR));
+ noexpr = strdup(nl_langinfo(NOEXPR));
+
+ if (yesstr == NULL || nostr == NULL ||
+ yesexpr == NULL || noexpr == NULL) {
+ FREE_MEM;
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ /* if problem with locale strings, use default values */
+ if (*yesstr == '\0' || *nostr == '\0' ||
+ *yesexpr == '\0' || *noexpr == '\0') {
+ FREE_MEM;
+ SET_DEFAULT_STRS;
+ fallback = 1;
+ }
+ /* Compile the yes and no expressions */
+ while (regcomp(&preg_yes, yesexpr, REG_EXTENDED | REG_NOSUB) != 0 ||
+ regcomp(&preg_no, noexpr, REG_EXTENDED | REG_NOSUB) != 0) {
+ if (fallback == 1) {
+ /* The fallback yesexpr failed, so exit */
+ errno = EINVAL;
+ return (-1);
+ }
+ /* The locale's yesexpr or noexpr failed so use fallback */
+ FREE_MEM;
+ SET_DEFAULT_STRS;
+ fallback = 1;
+ }
+ return (0);
+}
+
+static int
+yes_no(int (*func)(char *))
+{
+ int i, b;
+ char ans[LINE_MAX + 1];
+
+ /* Get user's answer */
+ for (i = 0; b = getchar(); i++) {
+ if (b == '\n' || b == '\0' || b == EOF)
+ break;
+ if (i < LINE_MAX)
+ ans[i] = b;
+ }
+ if (i >= LINE_MAX)
+ ans[LINE_MAX] = '\0';
+ else
+ ans[i] = '\0';
+
+ return (func(ans));
+}
+
+static int
+yes_no_check(char *ans, regex_t *reg1, regex_t *reg2)
+{
+ if (regexec(reg1, ans, 0, NULL, 0) == 0) {
+ if (regexec(reg2, ans, 0, NULL, 0) == 0) {
+ /* Both Expressions Match (reg2 conservative) */
+ return (0);
+ }
+ /* Match */
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * yes_check() returns 1 if the input string is matched by yesexpr and is
+ * not matched by noexpr; otherwise yes_check() returns 0.
+ */
+int
+yes_check(char *ans)
+{
+ return (yes_no_check(ans, &preg_yes, &preg_no));
+}
+
+/*
+ * no_check() returns 1 if the input string is matched by noexpr and is
+ * not matched by yesexpr; otherwise no_check() returns 0.
+ */
+int
+no_check(char *ans)
+{
+ return (yes_no_check(ans, &preg_no, &preg_yes));
+}
+
+int
+yes(void)
+{
+ return (yes_no(yes_check));
+}
+
+int
+no(void)
+{
+ return (yes_no(no_check));
+}