getresponse.c revision c536b1f93b31eba539c635a91be8ee2ab0fcb15a
1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License (the "License").
1N/A * You may not use this file except in compliance with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A/*
1N/A * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#include <stdio.h>
1N/A#include <string.h>
1N/A#include <stdlib.h>
1N/A#include <regex.h>
1N/A#include <locale.h>
1N/A#include <langinfo.h>
1N/A#include <limits.h>
1N/A#include <errno.h>
1N/A#include "getresponse.h"
1N/A
1N/A/* defaults - C locale values for yesstr, nostr, yesexpr (LC_MESSAGES) */
1N/A#define DEFAULT_YESSTR "yes"
1N/A#define DEFAULT_NOSTR "no"
1N/A#define DEFAULT_YESEXPR "^[yY]"
1N/A#define DEFAULT_NOEXPR "^[nN]"
1N/A
1N/A#define FREE_MEM \
1N/A if (yesstr) \
1N/A free(yesstr); \
1N/A if (nostr) \
1N/A free(nostr); \
1N/A if (yesexpr) \
1N/A free(yesexpr); \
1N/A if (noexpr) \
1N/A free(noexpr)
1N/A
1N/A#define SET_DEFAULT_STRS \
1N/A yesstr = DEFAULT_YESSTR; \
1N/A nostr = DEFAULT_NOSTR; \
1N/A yesexpr = DEFAULT_YESEXPR; \
1N/A noexpr = DEFAULT_NOEXPR;
1N/A
1N/A/* variables used by getresponse functions */
1N/Achar *yesstr = NULL;
1N/Achar *nostr = NULL;
1N/A
1N/A/* for regcomp()/regexec() yesexpr and noexpr */
1N/Astatic regex_t preg_yes, preg_no;
1N/A
1N/A/*
1N/A * 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 */
i = 0;
for (;;) {
b = getchar();
if (b == '\n' || b == '\0' || b == EOF)
break;
if (i < LINE_MAX)
ans[i] = b;
i++;
}
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));
}