3d63ea05cb8474d8036d3588cf8299306a994b8cas/*
3d63ea05cb8474d8036d3588cf8299306a994b8cas * CDDL HEADER START
3d63ea05cb8474d8036d3588cf8299306a994b8cas *
3d63ea05cb8474d8036d3588cf8299306a994b8cas * The contents of this file are subject to the terms of the
3d63ea05cb8474d8036d3588cf8299306a994b8cas * Common Development and Distribution License (the "License").
3d63ea05cb8474d8036d3588cf8299306a994b8cas * You may not use this file except in compliance with the License.
3d63ea05cb8474d8036d3588cf8299306a994b8cas *
3d63ea05cb8474d8036d3588cf8299306a994b8cas * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3d63ea05cb8474d8036d3588cf8299306a994b8cas * or http://www.opensolaris.org/os/licensing.
3d63ea05cb8474d8036d3588cf8299306a994b8cas * See the License for the specific language governing permissions
3d63ea05cb8474d8036d3588cf8299306a994b8cas * and limitations under the License.
3d63ea05cb8474d8036d3588cf8299306a994b8cas *
3d63ea05cb8474d8036d3588cf8299306a994b8cas * When distributing Covered Code, include this CDDL HEADER in each
3d63ea05cb8474d8036d3588cf8299306a994b8cas * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3d63ea05cb8474d8036d3588cf8299306a994b8cas * If applicable, add the following below this CDDL HEADER, with the
3d63ea05cb8474d8036d3588cf8299306a994b8cas * fields enclosed by brackets "[]" replaced with your own identifying
3d63ea05cb8474d8036d3588cf8299306a994b8cas * information: Portions Copyright [yyyy] [name of copyright owner]
3d63ea05cb8474d8036d3588cf8299306a994b8cas *
3d63ea05cb8474d8036d3588cf8299306a994b8cas * CDDL HEADER END
3d63ea05cb8474d8036d3588cf8299306a994b8cas */
3d63ea05cb8474d8036d3588cf8299306a994b8cas/*
3d63ea05cb8474d8036d3588cf8299306a994b8cas * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3d63ea05cb8474d8036d3588cf8299306a994b8cas * Use is subject to license terms.
3d63ea05cb8474d8036d3588cf8299306a994b8cas */
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <stdio.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <string.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <stdlib.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <regex.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <locale.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <langinfo.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <limits.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include <errno.h>
3d63ea05cb8474d8036d3588cf8299306a994b8cas#include "getresponse.h"
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas/* defaults - C locale values for yesstr, nostr, yesexpr (LC_MESSAGES) */
3d63ea05cb8474d8036d3588cf8299306a994b8cas#define DEFAULT_YESSTR "yes"
3d63ea05cb8474d8036d3588cf8299306a994b8cas#define DEFAULT_NOSTR "no"
3d63ea05cb8474d8036d3588cf8299306a994b8cas#define DEFAULT_YESEXPR "^[yY]"
3d63ea05cb8474d8036d3588cf8299306a994b8cas#define DEFAULT_NOEXPR "^[nN]"
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas#define FREE_MEM \
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (yesstr) \
3d63ea05cb8474d8036d3588cf8299306a994b8cas free(yesstr); \
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (nostr) \
3d63ea05cb8474d8036d3588cf8299306a994b8cas free(nostr); \
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (yesexpr) \
3d63ea05cb8474d8036d3588cf8299306a994b8cas free(yesexpr); \
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (noexpr) \
3d63ea05cb8474d8036d3588cf8299306a994b8cas free(noexpr)
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas#define SET_DEFAULT_STRS \
3d63ea05cb8474d8036d3588cf8299306a994b8cas yesstr = DEFAULT_YESSTR; \
3d63ea05cb8474d8036d3588cf8299306a994b8cas nostr = DEFAULT_NOSTR; \
3d63ea05cb8474d8036d3588cf8299306a994b8cas yesexpr = DEFAULT_YESEXPR; \
3d63ea05cb8474d8036d3588cf8299306a994b8cas noexpr = DEFAULT_NOEXPR;
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas/* variables used by getresponse functions */
3d63ea05cb8474d8036d3588cf8299306a994b8caschar *yesstr = NULL;
3d63ea05cb8474d8036d3588cf8299306a994b8caschar *nostr = NULL;
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas/* for regcomp()/regexec() yesexpr and noexpr */
3d63ea05cb8474d8036d3588cf8299306a994b8casstatic regex_t preg_yes, preg_no;
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas/*
3d63ea05cb8474d8036d3588cf8299306a994b8cas * This function compiles a regular expression that is used to match an
3d63ea05cb8474d8036d3588cf8299306a994b8cas * affirmative response from the user, and also assigns the strings used
3d63ea05cb8474d8036d3588cf8299306a994b8cas * in the prompts that request affirmative or negative responses. The
3d63ea05cb8474d8036d3588cf8299306a994b8cas * locale's values for YESEXPR, NOEXPR, YESSTR and NOSTR are used.
3d63ea05cb8474d8036d3588cf8299306a994b8cas *
3d63ea05cb8474d8036d3588cf8299306a994b8cas * If there are any problems using the locale's YESEXPR, NOEXPR, YESSTR or NOSTR
3d63ea05cb8474d8036d3588cf8299306a994b8cas * values, default values of YESEXPR, YESSTR and NOSTR will be used
3d63ea05cb8474d8036d3588cf8299306a994b8cas * as a fallback. The default values are the same as the C locale values.
3d63ea05cb8474d8036d3588cf8299306a994b8cas */
3d63ea05cb8474d8036d3588cf8299306a994b8casint
3d63ea05cb8474d8036d3588cf8299306a994b8casinit_yes(void)
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas int fallback = 0;
3d63ea05cb8474d8036d3588cf8299306a994b8cas char *yesexpr;
3d63ea05cb8474d8036d3588cf8299306a994b8cas char *noexpr;
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* get yes expression and strings for yes/no prompts */
3d63ea05cb8474d8036d3588cf8299306a994b8cas yesstr = strdup(nl_langinfo(YESSTR));
3d63ea05cb8474d8036d3588cf8299306a994b8cas nostr = strdup(nl_langinfo(NOSTR));
3d63ea05cb8474d8036d3588cf8299306a994b8cas yesexpr = strdup(nl_langinfo(YESEXPR));
3d63ea05cb8474d8036d3588cf8299306a994b8cas noexpr = strdup(nl_langinfo(NOEXPR));
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (yesstr == NULL || nostr == NULL ||
3d63ea05cb8474d8036d3588cf8299306a994b8cas yesexpr == NULL || noexpr == NULL) {
3d63ea05cb8474d8036d3588cf8299306a994b8cas FREE_MEM;
3d63ea05cb8474d8036d3588cf8299306a994b8cas errno = ENOMEM;
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (-1);
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* if problem with locale strings, use default values */
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (*yesstr == '\0' || *nostr == '\0' ||
3d63ea05cb8474d8036d3588cf8299306a994b8cas *yesexpr == '\0' || *noexpr == '\0') {
3d63ea05cb8474d8036d3588cf8299306a994b8cas FREE_MEM;
3d63ea05cb8474d8036d3588cf8299306a994b8cas SET_DEFAULT_STRS;
3d63ea05cb8474d8036d3588cf8299306a994b8cas fallback = 1;
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* Compile the yes and no expressions */
3d63ea05cb8474d8036d3588cf8299306a994b8cas while (regcomp(&preg_yes, yesexpr, REG_EXTENDED | REG_NOSUB) != 0 ||
3d63ea05cb8474d8036d3588cf8299306a994b8cas regcomp(&preg_no, noexpr, REG_EXTENDED | REG_NOSUB) != 0) {
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (fallback == 1) {
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* The fallback yesexpr failed, so exit */
3d63ea05cb8474d8036d3588cf8299306a994b8cas errno = EINVAL;
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (-1);
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* The locale's yesexpr or noexpr failed so use fallback */
3d63ea05cb8474d8036d3588cf8299306a994b8cas FREE_MEM;
3d63ea05cb8474d8036d3588cf8299306a994b8cas SET_DEFAULT_STRS;
3d63ea05cb8474d8036d3588cf8299306a994b8cas fallback = 1;
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (0);
3d63ea05cb8474d8036d3588cf8299306a994b8cas}
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8casstatic int
3d63ea05cb8474d8036d3588cf8299306a994b8casyes_no(int (*func)(char *))
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas int i, b;
3d63ea05cb8474d8036d3588cf8299306a994b8cas char ans[LINE_MAX + 1];
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* Get user's answer */
c536b1f93b31eba539c635a91be8ee2ab0fcb15aRobert Mustacchi i = 0;
c536b1f93b31eba539c635a91be8ee2ab0fcb15aRobert Mustacchi for (;;) {
c536b1f93b31eba539c635a91be8ee2ab0fcb15aRobert Mustacchi b = getchar();
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (b == '\n' || b == '\0' || b == EOF)
3d63ea05cb8474d8036d3588cf8299306a994b8cas break;
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (i < LINE_MAX)
3d63ea05cb8474d8036d3588cf8299306a994b8cas ans[i] = b;
c536b1f93b31eba539c635a91be8ee2ab0fcb15aRobert Mustacchi i++;
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (i >= LINE_MAX)
3d63ea05cb8474d8036d3588cf8299306a994b8cas ans[LINE_MAX] = '\0';
3d63ea05cb8474d8036d3588cf8299306a994b8cas else
3d63ea05cb8474d8036d3588cf8299306a994b8cas ans[i] = '\0';
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (func(ans));
3d63ea05cb8474d8036d3588cf8299306a994b8cas}
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8casstatic int
3d63ea05cb8474d8036d3588cf8299306a994b8casyes_no_check(char *ans, regex_t *reg1, regex_t *reg2)
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (regexec(reg1, ans, 0, NULL, 0) == 0) {
3d63ea05cb8474d8036d3588cf8299306a994b8cas if (regexec(reg2, ans, 0, NULL, 0) == 0) {
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* Both Expressions Match (reg2 conservative) */
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (0);
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas /* Match */
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (1);
3d63ea05cb8474d8036d3588cf8299306a994b8cas }
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (0);
3d63ea05cb8474d8036d3588cf8299306a994b8cas}
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas/*
3d63ea05cb8474d8036d3588cf8299306a994b8cas * yes_check() returns 1 if the input string is matched by yesexpr and is
3d63ea05cb8474d8036d3588cf8299306a994b8cas * not matched by noexpr; otherwise yes_check() returns 0.
3d63ea05cb8474d8036d3588cf8299306a994b8cas */
3d63ea05cb8474d8036d3588cf8299306a994b8casint
3d63ea05cb8474d8036d3588cf8299306a994b8casyes_check(char *ans)
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (yes_no_check(ans, &preg_yes, &preg_no));
3d63ea05cb8474d8036d3588cf8299306a994b8cas}
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8cas/*
3d63ea05cb8474d8036d3588cf8299306a994b8cas * no_check() returns 1 if the input string is matched by noexpr and is
3d63ea05cb8474d8036d3588cf8299306a994b8cas * not matched by yesexpr; otherwise no_check() returns 0.
3d63ea05cb8474d8036d3588cf8299306a994b8cas */
3d63ea05cb8474d8036d3588cf8299306a994b8casint
3d63ea05cb8474d8036d3588cf8299306a994b8casno_check(char *ans)
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (yes_no_check(ans, &preg_no, &preg_yes));
3d63ea05cb8474d8036d3588cf8299306a994b8cas}
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8casint
3d63ea05cb8474d8036d3588cf8299306a994b8casyes(void)
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (yes_no(yes_check));
3d63ea05cb8474d8036d3588cf8299306a994b8cas}
3d63ea05cb8474d8036d3588cf8299306a994b8cas
3d63ea05cb8474d8036d3588cf8299306a994b8casint
3d63ea05cb8474d8036d3588cf8299306a994b8casno(void)
3d63ea05cb8474d8036d3588cf8299306a994b8cas{
3d63ea05cb8474d8036d3588cf8299306a994b8cas return (yes_no(no_check));
3d63ea05cb8474d8036d3588cf8299306a994b8cas}