13d63ea05Sas /* 23d63ea05Sas * CDDL HEADER START 33d63ea05Sas * 43d63ea05Sas * The contents of this file are subject to the terms of the 53d63ea05Sas * Common Development and Distribution License (the "License"). 63d63ea05Sas * You may not use this file except in compliance with the License. 73d63ea05Sas * 83d63ea05Sas * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93d63ea05Sas * or http://www.opensolaris.org/os/licensing. 103d63ea05Sas * See the License for the specific language governing permissions 113d63ea05Sas * and limitations under the License. 123d63ea05Sas * 133d63ea05Sas * When distributing Covered Code, include this CDDL HEADER in each 143d63ea05Sas * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153d63ea05Sas * If applicable, add the following below this CDDL HEADER, with the 163d63ea05Sas * fields enclosed by brackets "[]" replaced with your own identifying 173d63ea05Sas * information: Portions Copyright [yyyy] [name of copyright owner] 183d63ea05Sas * 193d63ea05Sas * CDDL HEADER END 203d63ea05Sas */ 213d63ea05Sas /* 223d63ea05Sas * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233d63ea05Sas * Use is subject to license terms. 243d63ea05Sas */ 253d63ea05Sas 263d63ea05Sas #include <stdio.h> 273d63ea05Sas #include <string.h> 283d63ea05Sas #include <stdlib.h> 293d63ea05Sas #include <regex.h> 303d63ea05Sas #include <locale.h> 313d63ea05Sas #include <langinfo.h> 323d63ea05Sas #include <limits.h> 333d63ea05Sas #include <errno.h> 343d63ea05Sas #include "getresponse.h" 353d63ea05Sas 363d63ea05Sas /* defaults - C locale values for yesstr, nostr, yesexpr (LC_MESSAGES) */ 373d63ea05Sas #define DEFAULT_YESSTR "yes" 383d63ea05Sas #define DEFAULT_NOSTR "no" 393d63ea05Sas #define DEFAULT_YESEXPR "^[yY]" 403d63ea05Sas #define DEFAULT_NOEXPR "^[nN]" 413d63ea05Sas 423d63ea05Sas #define FREE_MEM \ 433d63ea05Sas if (yesstr) \ 443d63ea05Sas free(yesstr); \ 453d63ea05Sas if (nostr) \ 463d63ea05Sas free(nostr); \ 473d63ea05Sas if (yesexpr) \ 483d63ea05Sas free(yesexpr); \ 493d63ea05Sas if (noexpr) \ 503d63ea05Sas free(noexpr) 513d63ea05Sas 523d63ea05Sas #define SET_DEFAULT_STRS \ 533d63ea05Sas yesstr = DEFAULT_YESSTR; \ 543d63ea05Sas nostr = DEFAULT_NOSTR; \ 553d63ea05Sas yesexpr = DEFAULT_YESEXPR; \ 563d63ea05Sas noexpr = DEFAULT_NOEXPR; 573d63ea05Sas 583d63ea05Sas /* variables used by getresponse functions */ 593d63ea05Sas char *yesstr = NULL; 603d63ea05Sas char *nostr = NULL; 613d63ea05Sas 623d63ea05Sas /* for regcomp()/regexec() yesexpr and noexpr */ 633d63ea05Sas static regex_t preg_yes, preg_no; 643d63ea05Sas 653d63ea05Sas /* 663d63ea05Sas * This function compiles a regular expression that is used to match an 673d63ea05Sas * affirmative response from the user, and also assigns the strings used 683d63ea05Sas * in the prompts that request affirmative or negative responses. The 693d63ea05Sas * locale's values for YESEXPR, NOEXPR, YESSTR and NOSTR are used. 703d63ea05Sas * 713d63ea05Sas * If there are any problems using the locale's YESEXPR, NOEXPR, YESSTR or NOSTR 723d63ea05Sas * values, default values of YESEXPR, YESSTR and NOSTR will be used 733d63ea05Sas * as a fallback. The default values are the same as the C locale values. 743d63ea05Sas */ 753d63ea05Sas int 763d63ea05Sas init_yes(void) 773d63ea05Sas { 783d63ea05Sas int fallback = 0; 793d63ea05Sas char *yesexpr; 803d63ea05Sas char *noexpr; 813d63ea05Sas 823d63ea05Sas /* get yes expression and strings for yes/no prompts */ 833d63ea05Sas yesstr = strdup(nl_langinfo(YESSTR)); 843d63ea05Sas nostr = strdup(nl_langinfo(NOSTR)); 853d63ea05Sas yesexpr = strdup(nl_langinfo(YESEXPR)); 863d63ea05Sas noexpr = strdup(nl_langinfo(NOEXPR)); 873d63ea05Sas 883d63ea05Sas if (yesstr == NULL || nostr == NULL || 893d63ea05Sas yesexpr == NULL || noexpr == NULL) { 903d63ea05Sas FREE_MEM; 913d63ea05Sas errno = ENOMEM; 923d63ea05Sas return (-1); 933d63ea05Sas } 943d63ea05Sas 953d63ea05Sas /* if problem with locale strings, use default values */ 963d63ea05Sas if (*yesstr == '\0' || *nostr == '\0' || 973d63ea05Sas *yesexpr == '\0' || *noexpr == '\0') { 983d63ea05Sas FREE_MEM; 993d63ea05Sas SET_DEFAULT_STRS; 1003d63ea05Sas fallback = 1; 1013d63ea05Sas } 1023d63ea05Sas /* Compile the yes and no expressions */ 1033d63ea05Sas while (regcomp(&preg_yes, yesexpr, REG_EXTENDED | REG_NOSUB) != 0 || 1043d63ea05Sas regcomp(&preg_no, noexpr, REG_EXTENDED | REG_NOSUB) != 0) { 1053d63ea05Sas if (fallback == 1) { 1063d63ea05Sas /* The fallback yesexpr failed, so exit */ 1073d63ea05Sas errno = EINVAL; 1083d63ea05Sas return (-1); 1093d63ea05Sas } 1103d63ea05Sas /* The locale's yesexpr or noexpr failed so use fallback */ 1113d63ea05Sas FREE_MEM; 1123d63ea05Sas SET_DEFAULT_STRS; 1133d63ea05Sas fallback = 1; 1143d63ea05Sas } 1153d63ea05Sas return (0); 1163d63ea05Sas } 1173d63ea05Sas 1183d63ea05Sas static int 1193d63ea05Sas yes_no(int (*func)(char *)) 1203d63ea05Sas { 1213d63ea05Sas int i, b; 1223d63ea05Sas char ans[LINE_MAX + 1]; 1233d63ea05Sas 1243d63ea05Sas /* Get user's answer */ 125*c536b1f9SRobert Mustacchi i = 0; 126*c536b1f9SRobert Mustacchi for (;;) { 127*c536b1f9SRobert Mustacchi b = getchar(); 1283d63ea05Sas if (b == '\n' || b == '\0' || b == EOF) 1293d63ea05Sas break; 1303d63ea05Sas if (i < LINE_MAX) 1313d63ea05Sas ans[i] = b; 132*c536b1f9SRobert Mustacchi i++; 1333d63ea05Sas } 1343d63ea05Sas if (i >= LINE_MAX) 1353d63ea05Sas ans[LINE_MAX] = '\0'; 1363d63ea05Sas else 1373d63ea05Sas ans[i] = '\0'; 1383d63ea05Sas 1393d63ea05Sas return (func(ans)); 1403d63ea05Sas } 1413d63ea05Sas 1423d63ea05Sas static int 1433d63ea05Sas yes_no_check(char *ans, regex_t *reg1, regex_t *reg2) 1443d63ea05Sas { 1453d63ea05Sas if (regexec(reg1, ans, 0, NULL, 0) == 0) { 1463d63ea05Sas if (regexec(reg2, ans, 0, NULL, 0) == 0) { 1473d63ea05Sas /* Both Expressions Match (reg2 conservative) */ 1483d63ea05Sas return (0); 1493d63ea05Sas } 1503d63ea05Sas /* Match */ 1513d63ea05Sas return (1); 1523d63ea05Sas } 1533d63ea05Sas return (0); 1543d63ea05Sas } 1553d63ea05Sas 1563d63ea05Sas /* 1573d63ea05Sas * yes_check() returns 1 if the input string is matched by yesexpr and is 1583d63ea05Sas * not matched by noexpr; otherwise yes_check() returns 0. 1593d63ea05Sas */ 1603d63ea05Sas int 1613d63ea05Sas yes_check(char *ans) 1623d63ea05Sas { 1633d63ea05Sas return (yes_no_check(ans, &preg_yes, &preg_no)); 1643d63ea05Sas } 1653d63ea05Sas 1663d63ea05Sas /* 1673d63ea05Sas * no_check() returns 1 if the input string is matched by noexpr and is 1683d63ea05Sas * not matched by yesexpr; otherwise no_check() returns 0. 1693d63ea05Sas */ 1703d63ea05Sas int 1713d63ea05Sas no_check(char *ans) 1723d63ea05Sas { 1733d63ea05Sas return (yes_no_check(ans, &preg_no, &preg_yes)); 1743d63ea05Sas } 1753d63ea05Sas 1763d63ea05Sas int 1773d63ea05Sas yes(void) 1783d63ea05Sas { 1793d63ea05Sas return (yes_no(yes_check)); 1803d63ea05Sas } 1813d63ea05Sas 1823d63ea05Sas int 1833d63ea05Sas no(void) 1843d63ea05Sas { 1853d63ea05Sas return (yes_no(no_check)); 1863d63ea05Sas } 187