16007Sthurlow /* 26007Sthurlow * Copyright (c) 2000, Boris Popov 36007Sthurlow * All rights reserved. 46007Sthurlow * 56007Sthurlow * Redistribution and use in source and binary forms, with or without 66007Sthurlow * modification, are permitted provided that the following conditions 76007Sthurlow * are met: 86007Sthurlow * 1. Redistributions of source code must retain the above copyright 96007Sthurlow * notice, this list of conditions and the following disclaimer. 106007Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 116007Sthurlow * notice, this list of conditions and the following disclaimer in the 126007Sthurlow * documentation and/or other materials provided with the distribution. 136007Sthurlow * 3. All advertising materials mentioning features or use of this software 146007Sthurlow * must display the following acknowledgement: 156007Sthurlow * This product includes software developed by Boris Popov. 166007Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 176007Sthurlow * may be used to endorse or promote products derived from this software 186007Sthurlow * without specific prior written permission. 196007Sthurlow * 206007Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 216007Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 226007Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 236007Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 246007Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 256007Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 266007Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 276007Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 286007Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 296007Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 306007Sthurlow * SUCH DAMAGE. 316007Sthurlow * 326007Sthurlow * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $ 336007Sthurlow */ 346007Sthurlow 356007Sthurlow #include <fcntl.h> 366007Sthurlow #include <sys/types.h> 376007Sthurlow #include <sys/queue.h> 386007Sthurlow #include <sys/stat.h> 396007Sthurlow #include <ctype.h> 406007Sthurlow #include <errno.h> 416007Sthurlow #include <stdio.h> 426007Sthurlow #include <string.h> 436007Sthurlow #include <strings.h> 446007Sthurlow #include <stdlib.h> 456007Sthurlow #include <libintl.h> 466007Sthurlow #include <pwd.h> 476007Sthurlow #include <unistd.h> 486007Sthurlow #include <sys/debug.h> 496007Sthurlow 506007Sthurlow #include <cflib.h> 516007Sthurlow #include "rcfile_priv.h" 52*8271SGordon.Ross@Sun.COM extern int smb_debug; 536007Sthurlow 546007Sthurlow SLIST_HEAD(rcfile_head, rcfile); 556007Sthurlow static struct rcfile_head pf_head = {NULL}; 566007Sthurlow 576007Sthurlow static struct rcfile *rc_cachelookup(const char *filename); 586007Sthurlow struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname); 596007Sthurlow static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname); 606007Sthurlow static int rc_freesect(struct rcfile *rcp, struct rcsection *rsp); 616007Sthurlow struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname); 626007Sthurlow static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name, 636007Sthurlow const char *value); 646007Sthurlow static void rc_key_free(struct rckey *p); 656007Sthurlow static void rc_parse(struct rcfile *rcp); 666007Sthurlow 676007Sthurlow int insecure_nsmbrc; 686007Sthurlow 696007Sthurlow /* 706007Sthurlow * open rcfile and load its content, if already open - return previous handle 716007Sthurlow */ 726007Sthurlow int 736007Sthurlow rc_open(const char *filename, const char *mode, struct rcfile **rcfile) 746007Sthurlow { 756007Sthurlow struct rcfile *rcp; 766007Sthurlow FILE *f; 776007Sthurlow struct stat statbuf; 786007Sthurlow 796007Sthurlow rcp = rc_cachelookup(filename); 806007Sthurlow if (rcp) { 816007Sthurlow *rcfile = rcp; 826007Sthurlow return (0); 836007Sthurlow } 846007Sthurlow f = fopen(filename, mode); 856007Sthurlow if (f == NULL) 866007Sthurlow return (errno); 876007Sthurlow insecure_nsmbrc = 0; 886007Sthurlow if (fstat(fileno(f), &statbuf) >= 0 && 896007Sthurlow (statbuf.st_mode & 077) != 0) 906007Sthurlow insecure_nsmbrc = 1; 916007Sthurlow rcp = malloc(sizeof (struct rcfile)); 926007Sthurlow if (rcp == NULL) { 936007Sthurlow fclose(f); 946007Sthurlow return (ENOMEM); 956007Sthurlow } 966007Sthurlow bzero(rcp, sizeof (struct rcfile)); 976007Sthurlow rcp->rf_name = strdup(filename); 986007Sthurlow rcp->rf_f = f; 996007Sthurlow SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); 1006007Sthurlow rc_parse(rcp); 1016007Sthurlow *rcfile = rcp; 1026007Sthurlow return (0); 1036007Sthurlow } 1046007Sthurlow 1056007Sthurlow int 1066007Sthurlow rc_merge(const char *filename, struct rcfile **rcfile) 1076007Sthurlow { 1086007Sthurlow struct rcfile *rcp = *rcfile; 1096007Sthurlow FILE *f, *t; 1106007Sthurlow 1116007Sthurlow insecure_nsmbrc = 0; 1126007Sthurlow if (rcp == NULL) { 1136007Sthurlow return (rc_open(filename, "r", rcfile)); 1146007Sthurlow } 1156007Sthurlow f = fopen(filename, "r"); 1166007Sthurlow if (f == NULL) 1176007Sthurlow return (errno); 1186007Sthurlow t = rcp->rf_f; 1196007Sthurlow rcp->rf_f = f; 1206007Sthurlow rc_parse(rcp); 1216007Sthurlow rcp->rf_f = t; 1226007Sthurlow fclose(f); 1236007Sthurlow return (0); 1246007Sthurlow } 1256007Sthurlow 1266007Sthurlow int 1276007Sthurlow rc_merge_pipe(const char *command, struct rcfile **rcfile) 1286007Sthurlow { 1296007Sthurlow struct rcfile *rcp = *rcfile; 1306007Sthurlow FILE *f, *t; 1316007Sthurlow 1326007Sthurlow insecure_nsmbrc = 0; 1336007Sthurlow f = popen(command, "r"); 1346007Sthurlow if (f == NULL) 1356007Sthurlow return (errno); 1366007Sthurlow if (rcp == NULL) { 1376007Sthurlow rcp = malloc(sizeof (struct rcfile)); 1386007Sthurlow if (rcp == NULL) { 1396007Sthurlow fclose(f); 1406007Sthurlow return (ENOMEM); 1416007Sthurlow } 1426007Sthurlow *rcfile = rcp; 1436007Sthurlow bzero(rcp, sizeof (struct rcfile)); 1446007Sthurlow rcp->rf_name = strdup(command); 1456007Sthurlow rcp->rf_f = f; 1466007Sthurlow SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); 1476007Sthurlow rc_parse(rcp); 1486007Sthurlow } else { 1496007Sthurlow t = rcp->rf_f; 1506007Sthurlow rcp->rf_f = f; 1516007Sthurlow rc_parse(rcp); 1526007Sthurlow rcp->rf_f = t; 1536007Sthurlow } 1546007Sthurlow fclose(f); 1556007Sthurlow return (0); 1566007Sthurlow } 1576007Sthurlow 1586007Sthurlow int 1596007Sthurlow rc_close(struct rcfile *rcp) 1606007Sthurlow { 1616007Sthurlow struct rcsection *p, *n; 1626007Sthurlow 1636007Sthurlow fclose(rcp->rf_f); 1646007Sthurlow for (p = SLIST_FIRST(&rcp->rf_sect); p; ) { 1656007Sthurlow n = p; 1666007Sthurlow p = SLIST_NEXT(p, rs_next); 1676007Sthurlow rc_freesect(rcp, n); 1686007Sthurlow } 1696007Sthurlow free(rcp->rf_name); 1706007Sthurlow SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next); 1716007Sthurlow free(rcp); 1726007Sthurlow return (0); 1736007Sthurlow } 1746007Sthurlow 1756007Sthurlow static struct rcfile * 1766007Sthurlow rc_cachelookup(const char *filename) 1776007Sthurlow { 1786007Sthurlow struct rcfile *p; 1796007Sthurlow 1806007Sthurlow SLIST_FOREACH(p, &pf_head, rf_next) 1816007Sthurlow if (strcmp(filename, p->rf_name) == 0) 1826007Sthurlow return (p); 1836007Sthurlow return (0); 1846007Sthurlow } 1856007Sthurlow 1866007Sthurlow /* static */ struct rcsection * 1876007Sthurlow rc_findsect(struct rcfile *rcp, const char *sectname) 1886007Sthurlow { 1896007Sthurlow struct rcsection *p; 1906007Sthurlow 1916007Sthurlow SLIST_FOREACH(p, &rcp->rf_sect, rs_next) 1926007Sthurlow if (strcasecmp(p->rs_name, sectname) == 0) 1936007Sthurlow return (p); 1946007Sthurlow return (NULL); 1956007Sthurlow } 1966007Sthurlow 1976007Sthurlow static struct rcsection * 1986007Sthurlow rc_addsect(struct rcfile *rcp, const char *sectname) 1996007Sthurlow { 2006007Sthurlow struct rcsection *p; 2016007Sthurlow 2026007Sthurlow p = rc_findsect(rcp, sectname); 2036007Sthurlow if (p) 2046007Sthurlow return (p); 2056007Sthurlow p = malloc(sizeof (*p)); 2066007Sthurlow if (!p) 2076007Sthurlow return (NULL); 2086007Sthurlow p->rs_name = strdup(sectname); 2096007Sthurlow SLIST_INIT(&p->rs_keys); 2106007Sthurlow SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next); 2116007Sthurlow return (p); 2126007Sthurlow } 2136007Sthurlow 2146007Sthurlow static int 2156007Sthurlow rc_freesect(struct rcfile *rcp, struct rcsection *rsp) 2166007Sthurlow { 2176007Sthurlow struct rckey *p, *n; 2186007Sthurlow 2196007Sthurlow SLIST_REMOVE(&rcp->rf_sect, rsp, rcsection, rs_next); 2206007Sthurlow for (p = SLIST_FIRST(&rsp->rs_keys); p; ) { 2216007Sthurlow n = p; 2226007Sthurlow p = SLIST_NEXT(p, rk_next); 2236007Sthurlow rc_key_free(n); 2246007Sthurlow } 2256007Sthurlow free(rsp->rs_name); 2266007Sthurlow free(rsp); 2276007Sthurlow return (0); 2286007Sthurlow } 2296007Sthurlow 2306007Sthurlow /* static */ struct rckey * 2316007Sthurlow rc_sect_findkey(struct rcsection *rsp, const char *keyname) 2326007Sthurlow { 2336007Sthurlow struct rckey *p; 2346007Sthurlow 2356007Sthurlow SLIST_FOREACH(p, &rsp->rs_keys, rk_next) 2366007Sthurlow if (strcmp(p->rk_name, keyname) == 0) 2376007Sthurlow return (p); 2386007Sthurlow return (NULL); 2396007Sthurlow } 2406007Sthurlow 2416007Sthurlow static struct rckey * 2426007Sthurlow rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value) 2436007Sthurlow { 2446007Sthurlow struct rckey *p; 2456007Sthurlow 2466007Sthurlow p = rc_sect_findkey(rsp, name); 2476007Sthurlow if (!p) { 2486007Sthurlow p = malloc(sizeof (*p)); 2496007Sthurlow if (!p) 2506007Sthurlow return (NULL); 2516007Sthurlow SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next); 2526007Sthurlow p->rk_name = strdup(name); 2536007Sthurlow p->rk_value = value ? strdup(value) : strdup(""); 2546007Sthurlow } 2556007Sthurlow return (p); 2566007Sthurlow } 2576007Sthurlow 2586007Sthurlow #if 0 2596007Sthurlow void 2606007Sthurlow rc_sect_delkey(struct rcsection *rsp, struct rckey *p) 2616007Sthurlow { 2626007Sthurlow 2636007Sthurlow SLIST_REMOVE(&rsp->rs_keys, p, rckey, rk_next); 2646007Sthurlow rc_key_free(p); 2656007Sthurlow } 2666007Sthurlow #endif 2676007Sthurlow 2686007Sthurlow static void 2696007Sthurlow rc_key_free(struct rckey *p) 2706007Sthurlow { 2716007Sthurlow free(p->rk_value); 2726007Sthurlow free(p->rk_name); 2736007Sthurlow free(p); 2746007Sthurlow } 2756007Sthurlow 2766007Sthurlow enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue}; 2776007Sthurlow 2786007Sthurlow int home_nsmbrc = 0; 2796007Sthurlow 2806007Sthurlow static char *minauth[] = { 2816007Sthurlow "kerberos", 2826007Sthurlow "ntlmv2", 2836007Sthurlow "ntlm", 2846007Sthurlow "lm", 2856007Sthurlow "none", 2866007Sthurlow NULL 2876007Sthurlow }; 2886007Sthurlow 2896007Sthurlow static int 2906007Sthurlow eval_minauth(char *auth) 2916007Sthurlow { 2926007Sthurlow int i; 2936007Sthurlow 2946007Sthurlow for (i = 0; minauth[i]; i++) 2956007Sthurlow if (strcmp(auth, minauth[i]) == 0) 2966007Sthurlow break; 2976007Sthurlow return (i); 2986007Sthurlow } 2996007Sthurlow 3006007Sthurlow /* 3016007Sthurlow * Ensure that "minauth" is set to the highest level (lowest array offset) 3026007Sthurlow */ 3036007Sthurlow static void 3046007Sthurlow set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp, 3056007Sthurlow char *ptr) 3066007Sthurlow { 3076007Sthurlow int now, new; 3086007Sthurlow 3096007Sthurlow if (strcmp(rkp->rk_name, "minauth") == 0) { 3106007Sthurlow now = eval_minauth(rkp->rk_value); 3116007Sthurlow new = eval_minauth(ptr); 3126007Sthurlow if (new >= now) { 3136007Sthurlow #ifdef DEBUG 314*8271SGordon.Ross@Sun.COM if (smb_debug) 315*8271SGordon.Ross@Sun.COM printf( 316*8271SGordon.Ross@Sun.COM "set_value: rejecting %s=%s from %s\n", 317*8271SGordon.Ross@Sun.COM rkp->rk_name, ptr, home_nsmbrc ? 318*8271SGordon.Ross@Sun.COM "user file" : "SMF"); 3196007Sthurlow #endif 3206007Sthurlow return; 3216007Sthurlow } 3226007Sthurlow } 3236007Sthurlow #ifdef DEBUG 324*8271SGordon.Ross@Sun.COM if (smb_debug) 325*8271SGordon.Ross@Sun.COM printf("set_value: applying %s=%s from %s\n", 326*8271SGordon.Ross@Sun.COM rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF"); 3276007Sthurlow #endif 3286007Sthurlow rkp->rk_value = strdup(ptr); 3296007Sthurlow } 3306007Sthurlow 3316007Sthurlow static void 3326007Sthurlow rc_parse(struct rcfile *rcp) 3336007Sthurlow { 3346007Sthurlow FILE *f = rcp->rf_f; 3356007Sthurlow int state = stNewLine, c; 3366007Sthurlow struct rcsection *rsp = NULL; 3376007Sthurlow struct rckey *rkp = NULL; 3386007Sthurlow char buf[2048]; 3396007Sthurlow char *next = buf, *last = &buf[sizeof (buf)-1]; 3406007Sthurlow 3416007Sthurlow while ((c = getc(f)) != EOF) { 3426007Sthurlow if (c == '\r') 3436007Sthurlow continue; 3446007Sthurlow if (state == stNewLine) { 3456007Sthurlow next = buf; 3466007Sthurlow if (isspace(c)) 3476007Sthurlow continue; /* skip leading junk */ 3486007Sthurlow if (c == '[') { 3496007Sthurlow state = stHeader; 3506007Sthurlow rsp = NULL; 3516007Sthurlow continue; 3526007Sthurlow } 3536007Sthurlow if (c == '#' || c == ';') { 3546007Sthurlow state = stSkipToEOL; 3556007Sthurlow } else { /* something meaningfull */ 3566007Sthurlow state = stGetKey; 3576007Sthurlow } 3586007Sthurlow } 3596007Sthurlow /* ignore long lines */ 3606007Sthurlow if (state == stSkipToEOL || next == last) { 3616007Sthurlow if (c == '\n') { 3626007Sthurlow state = stNewLine; 3636007Sthurlow next = buf; 3646007Sthurlow } 3656007Sthurlow continue; 3666007Sthurlow } 3676007Sthurlow if (state == stHeader) { 3686007Sthurlow if (c == ']') { 3696007Sthurlow *next = 0; 3706007Sthurlow next = buf; 3716007Sthurlow rsp = rc_addsect(rcp, buf); 3726007Sthurlow state = stSkipToEOL; 3736007Sthurlow } else 3746007Sthurlow *next++ = c; 3756007Sthurlow continue; 3766007Sthurlow } 3776007Sthurlow if (state == stGetKey) { 3786007Sthurlow /* side effect: 'key name=' */ 3796007Sthurlow if (c == ' ' || c == '\t') 3806007Sthurlow continue; /* become 'keyname=' */ 3816007Sthurlow if (c == '\n') { /* silently ignore ... */ 3826007Sthurlow state = stNewLine; 3836007Sthurlow continue; 3846007Sthurlow } 3856007Sthurlow if (c != '=') { 3866007Sthurlow *next++ = c; 3876007Sthurlow continue; 3886007Sthurlow } 3896007Sthurlow *next = 0; 3906007Sthurlow if (rsp == NULL) { 3916007Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 3926007Sthurlow "Key '%s' defined before section\n"), buf); 3936007Sthurlow state = stSkipToEOL; 3946007Sthurlow continue; 3956007Sthurlow } 3966007Sthurlow if (home_nsmbrc && 3976007Sthurlow (strcmp(buf, "nbns") == 0 || 3986007Sthurlow strcmp(buf, "nbns_enable") == 0 || 399*8271SGordon.Ross@Sun.COM strcmp(buf, "nbns_broadcast") == 0 || 400*8271SGordon.Ross@Sun.COM strcmp(buf, "signing") == 0)) { 4016007Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 4026007Sthurlow "option %s may not be set " 4036007Sthurlow "in user .nsmbrc file\n"), buf); 4046007Sthurlow next = buf; 4056007Sthurlow state = stNewLine; 4066007Sthurlow continue; 4076007Sthurlow } 4086007Sthurlow if (insecure_nsmbrc && (strcmp(buf, "password") == 0)) { 4096007Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 4106007Sthurlow "Warning: .nsmbrc file not secure, " 4116007Sthurlow "ignoring passwords\n")); 4126007Sthurlow next = buf; 4136007Sthurlow state = stNewLine; 4146007Sthurlow continue; 4156007Sthurlow } 4166007Sthurlow rkp = rc_sect_addkey(rsp, buf, NULL); 4176007Sthurlow next = buf; 4186007Sthurlow state = stGetValue; 4196007Sthurlow continue; 4206007Sthurlow } 4216007Sthurlow /* only stGetValue left */ 4226007Sthurlow if (state != stGetValue) { 4236007Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 4246007Sthurlow "Well, I can't parse file '%s'\n"), rcp->rf_name); 4256007Sthurlow state = stSkipToEOL; 4266007Sthurlow } 4276007Sthurlow if (c != '\n') { 4286007Sthurlow *next++ = c; 4296007Sthurlow continue; 4306007Sthurlow } 4316007Sthurlow *next = 0; 4326007Sthurlow set_value(rcp, rsp, rkp, buf); 4336007Sthurlow state = stNewLine; 4346007Sthurlow rkp = NULL; 4356007Sthurlow } /* while */ 4366007Sthurlow if (c == EOF && state == stGetValue) { 4376007Sthurlow *next = 0; 4386007Sthurlow set_value(rcp, rsp, rkp, buf); 4396007Sthurlow } 4406007Sthurlow } 4416007Sthurlow 4426007Sthurlow int 4436007Sthurlow rc_getstringptr(struct rcfile *rcp, const char *section, const char *key, 4446007Sthurlow char **dest) 4456007Sthurlow { 4466007Sthurlow struct rcsection *rsp; 4476007Sthurlow struct rckey *rkp; 4486007Sthurlow 4496007Sthurlow *dest = NULL; 4506007Sthurlow rsp = rc_findsect(rcp, section); 4516007Sthurlow if (!rsp) 4526007Sthurlow return (ENOENT); 4536007Sthurlow rkp = rc_sect_findkey(rsp, key); 4546007Sthurlow if (!rkp) 4556007Sthurlow return (ENOENT); 4566007Sthurlow *dest = rkp->rk_value; 4576007Sthurlow return (0); 4586007Sthurlow } 4596007Sthurlow 4606007Sthurlow int 4616007Sthurlow rc_getstring(struct rcfile *rcp, const char *section, const char *key, 4626007Sthurlow size_t maxlen, char *dest) 4636007Sthurlow { 4646007Sthurlow char *value; 4656007Sthurlow int error; 4666007Sthurlow 4676007Sthurlow error = rc_getstringptr(rcp, section, key, &value); 4686007Sthurlow if (error) 4696007Sthurlow return (error); 4706007Sthurlow if (strlen(value) >= maxlen) { 4716007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 4726007Sthurlow "line too long for key '%s' in section '%s', max = %d\n"), 4736007Sthurlow key, section, maxlen); 4746007Sthurlow return (EINVAL); 4756007Sthurlow } 4766007Sthurlow strcpy(dest, value); 4776007Sthurlow return (0); 4786007Sthurlow } 4796007Sthurlow 4806007Sthurlow int 4816007Sthurlow rc_getint(struct rcfile *rcp, const char *section, const char *key, int *value) 4826007Sthurlow { 4836007Sthurlow struct rcsection *rsp; 4846007Sthurlow struct rckey *rkp; 4856007Sthurlow 4866007Sthurlow rsp = rc_findsect(rcp, section); 4876007Sthurlow if (!rsp) 4886007Sthurlow return (ENOENT); 4896007Sthurlow rkp = rc_sect_findkey(rsp, key); 4906007Sthurlow if (!rkp) 4916007Sthurlow return (ENOENT); 4926007Sthurlow errno = 0; 4936007Sthurlow *value = strtol(rkp->rk_value, NULL, 0); 4946007Sthurlow if (errno) { 4956007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 4966007Sthurlow "invalid int value '%s' for key '%s' in section '%s'\n"), 4976007Sthurlow rkp->rk_value, key, section); 4986007Sthurlow return (errno); 4996007Sthurlow } 5006007Sthurlow return (0); 5016007Sthurlow } 5026007Sthurlow 5036007Sthurlow /* 5046007Sthurlow * 1,yes,true 5056007Sthurlow * 0,no,false 5066007Sthurlow */ 5076007Sthurlow int 5086007Sthurlow rc_getbool(struct rcfile *rcp, const char *section, const char *key, int *value) 5096007Sthurlow { 5106007Sthurlow struct rcsection *rsp; 5116007Sthurlow struct rckey *rkp; 5126007Sthurlow char *p; 5136007Sthurlow 5146007Sthurlow rsp = rc_findsect(rcp, section); 5156007Sthurlow if (!rsp) 5166007Sthurlow return (ENOENT); 5176007Sthurlow rkp = rc_sect_findkey(rsp, key); 5186007Sthurlow if (!rkp) 5196007Sthurlow return (ENOENT); 5206007Sthurlow p = rkp->rk_value; 5216007Sthurlow while (*p && isspace(*p)) p++; 5226007Sthurlow if (*p == '0' || 5236007Sthurlow strcasecmp(p, "no") == 0 || 5246007Sthurlow strcasecmp(p, "false") == 0) { 5256007Sthurlow *value = 0; 5266007Sthurlow return (0); 5276007Sthurlow } 5286007Sthurlow if (*p == '1' || 5296007Sthurlow strcasecmp(p, "yes") == 0 || 5306007Sthurlow strcasecmp(p, "true") == 0) { 5316007Sthurlow *value = 1; 5326007Sthurlow return (0); 5336007Sthurlow } 5346007Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 5356007Sthurlow "invalid boolean value '%s' for key '%s' in section '%s' \n"), 5366007Sthurlow p, key, section); 5376007Sthurlow return (EINVAL); 5386007Sthurlow } 5396007Sthurlow 5406007Sthurlow /* 5416007Sthurlow * Unified command line/rc file parser 5426007Sthurlow */ 5436007Sthurlow int 5446007Sthurlow opt_args_parse(struct rcfile *rcp, struct opt_args *ap, const char *sect, 5456007Sthurlow opt_callback_t *callback) 5466007Sthurlow { 5476007Sthurlow int len, error; 5486007Sthurlow 5496007Sthurlow for (; ap->opt; ap++) { 5506007Sthurlow switch (ap->type) { 5516007Sthurlow case OPTARG_STR: 5526007Sthurlow if (rc_getstringptr(rcp, sect, ap->name, &ap->str) != 0) 5536007Sthurlow break; 5546007Sthurlow len = strlen(ap->str); 5556007Sthurlow if (len > ap->ival) { 5566007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 5576007Sthurlow "rc: argument for option '%c' (%s) too long\n"), 5586007Sthurlow ap->opt, ap->name); 5596007Sthurlow return (EINVAL); 5606007Sthurlow } 5616007Sthurlow callback(ap); 5626007Sthurlow break; 5636007Sthurlow case OPTARG_BOOL: 5646007Sthurlow error = rc_getbool(rcp, sect, ap->name, &ap->ival); 5656007Sthurlow if (error == ENOENT) 5666007Sthurlow break; 5676007Sthurlow if (error) 5686007Sthurlow return (EINVAL); 5696007Sthurlow callback(ap); 5706007Sthurlow break; 5716007Sthurlow case OPTARG_INT: 5726007Sthurlow if (rc_getint(rcp, sect, ap->name, &ap->ival) != 0) 5736007Sthurlow break; 5746007Sthurlow if (((ap->flag & OPTFL_HAVEMIN) && 5756007Sthurlow ap->ival < ap->min) || 5766007Sthurlow ((ap->flag & OPTFL_HAVEMAX) && 5776007Sthurlow ap->ival > ap->max)) { 5786007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 5796007Sthurlow "rc: argument for option '%c' (%s) " 5806007Sthurlow "should be in [%d-%d] range\n"), 5816007Sthurlow ap->opt, ap->name, ap->min, ap->max); 5826007Sthurlow return (EINVAL); 5836007Sthurlow } 5846007Sthurlow callback(ap); 5856007Sthurlow break; 5866007Sthurlow default: 5876007Sthurlow break; 5886007Sthurlow } 5896007Sthurlow } 5906007Sthurlow return (0); 5916007Sthurlow } 5926007Sthurlow 5936007Sthurlow int 5946007Sthurlow opt_args_parseopt(struct opt_args *ap, int opt, char *arg, 5956007Sthurlow opt_callback_t *callback) 5966007Sthurlow { 5976007Sthurlow int len; 5986007Sthurlow 5996007Sthurlow for (; ap->opt; ap++) { 6006007Sthurlow if (ap->opt != opt) 6016007Sthurlow continue; 6026007Sthurlow switch (ap->type) { 6036007Sthurlow case OPTARG_STR: 6046007Sthurlow ap->str = arg; 6056007Sthurlow if (arg) { 6066007Sthurlow len = strlen(ap->str); 6076007Sthurlow if (len > ap->ival) { 6086007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 6096007Sthurlow "opt: Argument for option '%c' (%s) too long\n"), 6106007Sthurlow ap->opt, ap->name); 6116007Sthurlow return (EINVAL); 6126007Sthurlow } 6136007Sthurlow callback(ap); 6146007Sthurlow } 6156007Sthurlow break; 6166007Sthurlow case OPTARG_BOOL: 6176007Sthurlow ap->ival = 0; 6186007Sthurlow callback(ap); 6196007Sthurlow break; 6206007Sthurlow case OPTARG_INT: 6216007Sthurlow errno = 0; 6226007Sthurlow ap->ival = strtol(arg, NULL, 0); 6236007Sthurlow if (errno) { 6246007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 6256007Sthurlow "opt: Invalid integer value for " 6266007Sthurlow "option '%c' (%s).\n"), 6276007Sthurlow ap->opt, ap->name); 6286007Sthurlow return (EINVAL); 6296007Sthurlow } 6306007Sthurlow if (((ap->flag & OPTFL_HAVEMIN) && 6316007Sthurlow (ap->ival < ap->min)) || 6326007Sthurlow ((ap->flag & OPTFL_HAVEMAX) && 6336007Sthurlow (ap->ival > ap->max))) { 6346007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 6356007Sthurlow "opt: Argument for option '%c' (%s) " 6366007Sthurlow "should be in [%d-%d] range\n"), 6376007Sthurlow ap->opt, ap->name, ap->min, ap->max); 6386007Sthurlow return (EINVAL); 6396007Sthurlow } 6406007Sthurlow callback(ap); 6416007Sthurlow break; 6426007Sthurlow default: 6436007Sthurlow break; 6446007Sthurlow } 6456007Sthurlow break; 6466007Sthurlow } 6476007Sthurlow return (0); 6486007Sthurlow } 649