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