1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 3*4bff34e3Sthurlow * All rights reserved. 4*4bff34e3Sthurlow * 5*4bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 6*4bff34e3Sthurlow * modification, are permitted provided that the following conditions 7*4bff34e3Sthurlow * are met: 8*4bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 9*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 10*4bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 11*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 12*4bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 13*4bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 14*4bff34e3Sthurlow * must display the following acknowledgement: 15*4bff34e3Sthurlow * This product includes software developed by Boris Popov. 16*4bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 17*4bff34e3Sthurlow * may be used to endorse or promote products derived from this software 18*4bff34e3Sthurlow * without specific prior written permission. 19*4bff34e3Sthurlow * 20*4bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4bff34e3Sthurlow * SUCH DAMAGE. 31*4bff34e3Sthurlow * 32*4bff34e3Sthurlow * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $ 33*4bff34e3Sthurlow */ 34*4bff34e3Sthurlow 35*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 36*4bff34e3Sthurlow 37*4bff34e3Sthurlow #include <fcntl.h> 38*4bff34e3Sthurlow #include <sys/types.h> 39*4bff34e3Sthurlow #include <sys/queue.h> 40*4bff34e3Sthurlow #include <sys/stat.h> 41*4bff34e3Sthurlow #include <ctype.h> 42*4bff34e3Sthurlow #include <errno.h> 43*4bff34e3Sthurlow #include <stdio.h> 44*4bff34e3Sthurlow #include <string.h> 45*4bff34e3Sthurlow #include <strings.h> 46*4bff34e3Sthurlow #include <stdlib.h> 47*4bff34e3Sthurlow #include <libintl.h> 48*4bff34e3Sthurlow #include <pwd.h> 49*4bff34e3Sthurlow #include <unistd.h> 50*4bff34e3Sthurlow #include <sys/debug.h> 51*4bff34e3Sthurlow 52*4bff34e3Sthurlow #include <cflib.h> 53*4bff34e3Sthurlow #include "rcfile_priv.h" 54*4bff34e3Sthurlow 55*4bff34e3Sthurlow SLIST_HEAD(rcfile_head, rcfile); 56*4bff34e3Sthurlow static struct rcfile_head pf_head = {NULL}; 57*4bff34e3Sthurlow 58*4bff34e3Sthurlow static struct rcfile *rc_cachelookup(const char *filename); 59*4bff34e3Sthurlow struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname); 60*4bff34e3Sthurlow static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname); 61*4bff34e3Sthurlow static int rc_freesect(struct rcfile *rcp, struct rcsection *rsp); 62*4bff34e3Sthurlow struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname); 63*4bff34e3Sthurlow static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name, 64*4bff34e3Sthurlow const char *value); 65*4bff34e3Sthurlow static void rc_key_free(struct rckey *p); 66*4bff34e3Sthurlow static void rc_parse(struct rcfile *rcp); 67*4bff34e3Sthurlow 68*4bff34e3Sthurlow int insecure_nsmbrc; 69*4bff34e3Sthurlow 70*4bff34e3Sthurlow /* 71*4bff34e3Sthurlow * open rcfile and load its content, if already open - return previous handle 72*4bff34e3Sthurlow */ 73*4bff34e3Sthurlow int 74*4bff34e3Sthurlow rc_open(const char *filename, const char *mode, struct rcfile **rcfile) 75*4bff34e3Sthurlow { 76*4bff34e3Sthurlow struct rcfile *rcp; 77*4bff34e3Sthurlow FILE *f; 78*4bff34e3Sthurlow struct stat statbuf; 79*4bff34e3Sthurlow 80*4bff34e3Sthurlow rcp = rc_cachelookup(filename); 81*4bff34e3Sthurlow if (rcp) { 82*4bff34e3Sthurlow *rcfile = rcp; 83*4bff34e3Sthurlow return (0); 84*4bff34e3Sthurlow } 85*4bff34e3Sthurlow f = fopen(filename, mode); 86*4bff34e3Sthurlow if (f == NULL) 87*4bff34e3Sthurlow return (errno); 88*4bff34e3Sthurlow insecure_nsmbrc = 0; 89*4bff34e3Sthurlow if (fstat(fileno(f), &statbuf) >= 0 && 90*4bff34e3Sthurlow (statbuf.st_mode & 077) != 0) 91*4bff34e3Sthurlow insecure_nsmbrc = 1; 92*4bff34e3Sthurlow rcp = malloc(sizeof (struct rcfile)); 93*4bff34e3Sthurlow if (rcp == NULL) { 94*4bff34e3Sthurlow fclose(f); 95*4bff34e3Sthurlow return (ENOMEM); 96*4bff34e3Sthurlow } 97*4bff34e3Sthurlow bzero(rcp, sizeof (struct rcfile)); 98*4bff34e3Sthurlow rcp->rf_name = strdup(filename); 99*4bff34e3Sthurlow rcp->rf_f = f; 100*4bff34e3Sthurlow SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); 101*4bff34e3Sthurlow rc_parse(rcp); 102*4bff34e3Sthurlow *rcfile = rcp; 103*4bff34e3Sthurlow return (0); 104*4bff34e3Sthurlow } 105*4bff34e3Sthurlow 106*4bff34e3Sthurlow int 107*4bff34e3Sthurlow rc_merge(const char *filename, struct rcfile **rcfile) 108*4bff34e3Sthurlow { 109*4bff34e3Sthurlow struct rcfile *rcp = *rcfile; 110*4bff34e3Sthurlow FILE *f, *t; 111*4bff34e3Sthurlow 112*4bff34e3Sthurlow insecure_nsmbrc = 0; 113*4bff34e3Sthurlow if (rcp == NULL) { 114*4bff34e3Sthurlow return (rc_open(filename, "r", rcfile)); 115*4bff34e3Sthurlow } 116*4bff34e3Sthurlow f = fopen(filename, "r"); 117*4bff34e3Sthurlow if (f == NULL) 118*4bff34e3Sthurlow return (errno); 119*4bff34e3Sthurlow t = rcp->rf_f; 120*4bff34e3Sthurlow rcp->rf_f = f; 121*4bff34e3Sthurlow rc_parse(rcp); 122*4bff34e3Sthurlow rcp->rf_f = t; 123*4bff34e3Sthurlow fclose(f); 124*4bff34e3Sthurlow return (0); 125*4bff34e3Sthurlow } 126*4bff34e3Sthurlow 127*4bff34e3Sthurlow int 128*4bff34e3Sthurlow rc_merge_pipe(const char *command, struct rcfile **rcfile) 129*4bff34e3Sthurlow { 130*4bff34e3Sthurlow struct rcfile *rcp = *rcfile; 131*4bff34e3Sthurlow FILE *f, *t; 132*4bff34e3Sthurlow 133*4bff34e3Sthurlow insecure_nsmbrc = 0; 134*4bff34e3Sthurlow f = popen(command, "r"); 135*4bff34e3Sthurlow if (f == NULL) 136*4bff34e3Sthurlow return (errno); 137*4bff34e3Sthurlow if (rcp == NULL) { 138*4bff34e3Sthurlow rcp = malloc(sizeof (struct rcfile)); 139*4bff34e3Sthurlow if (rcp == NULL) { 140*4bff34e3Sthurlow fclose(f); 141*4bff34e3Sthurlow return (ENOMEM); 142*4bff34e3Sthurlow } 143*4bff34e3Sthurlow *rcfile = rcp; 144*4bff34e3Sthurlow bzero(rcp, sizeof (struct rcfile)); 145*4bff34e3Sthurlow rcp->rf_name = strdup(command); 146*4bff34e3Sthurlow rcp->rf_f = f; 147*4bff34e3Sthurlow SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); 148*4bff34e3Sthurlow rc_parse(rcp); 149*4bff34e3Sthurlow } else { 150*4bff34e3Sthurlow t = rcp->rf_f; 151*4bff34e3Sthurlow rcp->rf_f = f; 152*4bff34e3Sthurlow rc_parse(rcp); 153*4bff34e3Sthurlow rcp->rf_f = t; 154*4bff34e3Sthurlow } 155*4bff34e3Sthurlow fclose(f); 156*4bff34e3Sthurlow return (0); 157*4bff34e3Sthurlow } 158*4bff34e3Sthurlow 159*4bff34e3Sthurlow int 160*4bff34e3Sthurlow rc_close(struct rcfile *rcp) 161*4bff34e3Sthurlow { 162*4bff34e3Sthurlow struct rcsection *p, *n; 163*4bff34e3Sthurlow 164*4bff34e3Sthurlow fclose(rcp->rf_f); 165*4bff34e3Sthurlow for (p = SLIST_FIRST(&rcp->rf_sect); p; ) { 166*4bff34e3Sthurlow n = p; 167*4bff34e3Sthurlow p = SLIST_NEXT(p, rs_next); 168*4bff34e3Sthurlow rc_freesect(rcp, n); 169*4bff34e3Sthurlow } 170*4bff34e3Sthurlow free(rcp->rf_name); 171*4bff34e3Sthurlow SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next); 172*4bff34e3Sthurlow free(rcp); 173*4bff34e3Sthurlow return (0); 174*4bff34e3Sthurlow } 175*4bff34e3Sthurlow 176*4bff34e3Sthurlow static struct rcfile * 177*4bff34e3Sthurlow rc_cachelookup(const char *filename) 178*4bff34e3Sthurlow { 179*4bff34e3Sthurlow struct rcfile *p; 180*4bff34e3Sthurlow 181*4bff34e3Sthurlow SLIST_FOREACH(p, &pf_head, rf_next) 182*4bff34e3Sthurlow if (strcmp(filename, p->rf_name) == 0) 183*4bff34e3Sthurlow return (p); 184*4bff34e3Sthurlow return (0); 185*4bff34e3Sthurlow } 186*4bff34e3Sthurlow 187*4bff34e3Sthurlow /* static */ struct rcsection * 188*4bff34e3Sthurlow rc_findsect(struct rcfile *rcp, const char *sectname) 189*4bff34e3Sthurlow { 190*4bff34e3Sthurlow struct rcsection *p; 191*4bff34e3Sthurlow 192*4bff34e3Sthurlow SLIST_FOREACH(p, &rcp->rf_sect, rs_next) 193*4bff34e3Sthurlow if (strcasecmp(p->rs_name, sectname) == 0) 194*4bff34e3Sthurlow return (p); 195*4bff34e3Sthurlow return (NULL); 196*4bff34e3Sthurlow } 197*4bff34e3Sthurlow 198*4bff34e3Sthurlow static struct rcsection * 199*4bff34e3Sthurlow rc_addsect(struct rcfile *rcp, const char *sectname) 200*4bff34e3Sthurlow { 201*4bff34e3Sthurlow struct rcsection *p; 202*4bff34e3Sthurlow 203*4bff34e3Sthurlow p = rc_findsect(rcp, sectname); 204*4bff34e3Sthurlow if (p) 205*4bff34e3Sthurlow return (p); 206*4bff34e3Sthurlow p = malloc(sizeof (*p)); 207*4bff34e3Sthurlow if (!p) 208*4bff34e3Sthurlow return (NULL); 209*4bff34e3Sthurlow p->rs_name = strdup(sectname); 210*4bff34e3Sthurlow SLIST_INIT(&p->rs_keys); 211*4bff34e3Sthurlow SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next); 212*4bff34e3Sthurlow return (p); 213*4bff34e3Sthurlow } 214*4bff34e3Sthurlow 215*4bff34e3Sthurlow static int 216*4bff34e3Sthurlow rc_freesect(struct rcfile *rcp, struct rcsection *rsp) 217*4bff34e3Sthurlow { 218*4bff34e3Sthurlow struct rckey *p, *n; 219*4bff34e3Sthurlow 220*4bff34e3Sthurlow SLIST_REMOVE(&rcp->rf_sect, rsp, rcsection, rs_next); 221*4bff34e3Sthurlow for (p = SLIST_FIRST(&rsp->rs_keys); p; ) { 222*4bff34e3Sthurlow n = p; 223*4bff34e3Sthurlow p = SLIST_NEXT(p, rk_next); 224*4bff34e3Sthurlow rc_key_free(n); 225*4bff34e3Sthurlow } 226*4bff34e3Sthurlow free(rsp->rs_name); 227*4bff34e3Sthurlow free(rsp); 228*4bff34e3Sthurlow return (0); 229*4bff34e3Sthurlow } 230*4bff34e3Sthurlow 231*4bff34e3Sthurlow /* static */ struct rckey * 232*4bff34e3Sthurlow rc_sect_findkey(struct rcsection *rsp, const char *keyname) 233*4bff34e3Sthurlow { 234*4bff34e3Sthurlow struct rckey *p; 235*4bff34e3Sthurlow 236*4bff34e3Sthurlow SLIST_FOREACH(p, &rsp->rs_keys, rk_next) 237*4bff34e3Sthurlow if (strcmp(p->rk_name, keyname) == 0) 238*4bff34e3Sthurlow return (p); 239*4bff34e3Sthurlow return (NULL); 240*4bff34e3Sthurlow } 241*4bff34e3Sthurlow 242*4bff34e3Sthurlow static struct rckey * 243*4bff34e3Sthurlow rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value) 244*4bff34e3Sthurlow { 245*4bff34e3Sthurlow struct rckey *p; 246*4bff34e3Sthurlow 247*4bff34e3Sthurlow p = rc_sect_findkey(rsp, name); 248*4bff34e3Sthurlow if (!p) { 249*4bff34e3Sthurlow p = malloc(sizeof (*p)); 250*4bff34e3Sthurlow if (!p) 251*4bff34e3Sthurlow return (NULL); 252*4bff34e3Sthurlow SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next); 253*4bff34e3Sthurlow p->rk_name = strdup(name); 254*4bff34e3Sthurlow p->rk_value = value ? strdup(value) : strdup(""); 255*4bff34e3Sthurlow } 256*4bff34e3Sthurlow return (p); 257*4bff34e3Sthurlow } 258*4bff34e3Sthurlow 259*4bff34e3Sthurlow #if 0 260*4bff34e3Sthurlow void 261*4bff34e3Sthurlow rc_sect_delkey(struct rcsection *rsp, struct rckey *p) 262*4bff34e3Sthurlow { 263*4bff34e3Sthurlow 264*4bff34e3Sthurlow SLIST_REMOVE(&rsp->rs_keys, p, rckey, rk_next); 265*4bff34e3Sthurlow rc_key_free(p); 266*4bff34e3Sthurlow } 267*4bff34e3Sthurlow #endif 268*4bff34e3Sthurlow 269*4bff34e3Sthurlow static void 270*4bff34e3Sthurlow rc_key_free(struct rckey *p) 271*4bff34e3Sthurlow { 272*4bff34e3Sthurlow free(p->rk_value); 273*4bff34e3Sthurlow free(p->rk_name); 274*4bff34e3Sthurlow free(p); 275*4bff34e3Sthurlow } 276*4bff34e3Sthurlow 277*4bff34e3Sthurlow enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue}; 278*4bff34e3Sthurlow 279*4bff34e3Sthurlow int home_nsmbrc = 0; 280*4bff34e3Sthurlow 281*4bff34e3Sthurlow static char *minauth[] = { 282*4bff34e3Sthurlow "kerberos", 283*4bff34e3Sthurlow "ntlmv2", 284*4bff34e3Sthurlow "ntlm", 285*4bff34e3Sthurlow "lm", 286*4bff34e3Sthurlow "none", 287*4bff34e3Sthurlow NULL 288*4bff34e3Sthurlow }; 289*4bff34e3Sthurlow 290*4bff34e3Sthurlow static int 291*4bff34e3Sthurlow eval_minauth(char *auth) 292*4bff34e3Sthurlow { 293*4bff34e3Sthurlow int i; 294*4bff34e3Sthurlow 295*4bff34e3Sthurlow for (i = 0; minauth[i]; i++) 296*4bff34e3Sthurlow if (strcmp(auth, minauth[i]) == 0) 297*4bff34e3Sthurlow break; 298*4bff34e3Sthurlow return (i); 299*4bff34e3Sthurlow } 300*4bff34e3Sthurlow 301*4bff34e3Sthurlow /* 302*4bff34e3Sthurlow * Ensure that "minauth" is set to the highest level (lowest array offset) 303*4bff34e3Sthurlow */ 304*4bff34e3Sthurlow static void 305*4bff34e3Sthurlow set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp, 306*4bff34e3Sthurlow char *ptr) 307*4bff34e3Sthurlow { 308*4bff34e3Sthurlow int now, new; 309*4bff34e3Sthurlow 310*4bff34e3Sthurlow if (strcmp(rkp->rk_name, "minauth") == 0) { 311*4bff34e3Sthurlow now = eval_minauth(rkp->rk_value); 312*4bff34e3Sthurlow new = eval_minauth(ptr); 313*4bff34e3Sthurlow if (new >= now) { 314*4bff34e3Sthurlow #ifdef DEBUG 315*4bff34e3Sthurlow printf("set_value: rejecting %s=%s from %s\n", 316*4bff34e3Sthurlow rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF"); 317*4bff34e3Sthurlow #endif 318*4bff34e3Sthurlow return; 319*4bff34e3Sthurlow } 320*4bff34e3Sthurlow } 321*4bff34e3Sthurlow #ifdef DEBUG 322*4bff34e3Sthurlow printf("set_value: applying %s=%s from %s\n", 323*4bff34e3Sthurlow rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF"); 324*4bff34e3Sthurlow #endif 325*4bff34e3Sthurlow rkp->rk_value = strdup(ptr); 326*4bff34e3Sthurlow } 327*4bff34e3Sthurlow 328*4bff34e3Sthurlow static void 329*4bff34e3Sthurlow rc_parse(struct rcfile *rcp) 330*4bff34e3Sthurlow { 331*4bff34e3Sthurlow FILE *f = rcp->rf_f; 332*4bff34e3Sthurlow int state = stNewLine, c; 333*4bff34e3Sthurlow struct rcsection *rsp = NULL; 334*4bff34e3Sthurlow struct rckey *rkp = NULL; 335*4bff34e3Sthurlow char buf[2048]; 336*4bff34e3Sthurlow char *next = buf, *last = &buf[sizeof (buf)-1]; 337*4bff34e3Sthurlow 338*4bff34e3Sthurlow while ((c = getc(f)) != EOF) { 339*4bff34e3Sthurlow if (c == '\r') 340*4bff34e3Sthurlow continue; 341*4bff34e3Sthurlow if (state == stNewLine) { 342*4bff34e3Sthurlow next = buf; 343*4bff34e3Sthurlow if (isspace(c)) 344*4bff34e3Sthurlow continue; /* skip leading junk */ 345*4bff34e3Sthurlow if (c == '[') { 346*4bff34e3Sthurlow state = stHeader; 347*4bff34e3Sthurlow rsp = NULL; 348*4bff34e3Sthurlow continue; 349*4bff34e3Sthurlow } 350*4bff34e3Sthurlow if (c == '#' || c == ';') { 351*4bff34e3Sthurlow state = stSkipToEOL; 352*4bff34e3Sthurlow } else { /* something meaningfull */ 353*4bff34e3Sthurlow state = stGetKey; 354*4bff34e3Sthurlow } 355*4bff34e3Sthurlow } 356*4bff34e3Sthurlow /* ignore long lines */ 357*4bff34e3Sthurlow if (state == stSkipToEOL || next == last) { 358*4bff34e3Sthurlow if (c == '\n') { 359*4bff34e3Sthurlow state = stNewLine; 360*4bff34e3Sthurlow next = buf; 361*4bff34e3Sthurlow } 362*4bff34e3Sthurlow continue; 363*4bff34e3Sthurlow } 364*4bff34e3Sthurlow if (state == stHeader) { 365*4bff34e3Sthurlow if (c == ']') { 366*4bff34e3Sthurlow *next = 0; 367*4bff34e3Sthurlow next = buf; 368*4bff34e3Sthurlow rsp = rc_addsect(rcp, buf); 369*4bff34e3Sthurlow state = stSkipToEOL; 370*4bff34e3Sthurlow } else 371*4bff34e3Sthurlow *next++ = c; 372*4bff34e3Sthurlow continue; 373*4bff34e3Sthurlow } 374*4bff34e3Sthurlow if (state == stGetKey) { 375*4bff34e3Sthurlow /* side effect: 'key name=' */ 376*4bff34e3Sthurlow if (c == ' ' || c == '\t') 377*4bff34e3Sthurlow continue; /* become 'keyname=' */ 378*4bff34e3Sthurlow if (c == '\n') { /* silently ignore ... */ 379*4bff34e3Sthurlow state = stNewLine; 380*4bff34e3Sthurlow continue; 381*4bff34e3Sthurlow } 382*4bff34e3Sthurlow if (c != '=') { 383*4bff34e3Sthurlow *next++ = c; 384*4bff34e3Sthurlow continue; 385*4bff34e3Sthurlow } 386*4bff34e3Sthurlow *next = 0; 387*4bff34e3Sthurlow if (rsp == NULL) { 388*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 389*4bff34e3Sthurlow "Key '%s' defined before section\n"), buf); 390*4bff34e3Sthurlow state = stSkipToEOL; 391*4bff34e3Sthurlow continue; 392*4bff34e3Sthurlow } 393*4bff34e3Sthurlow if (home_nsmbrc && 394*4bff34e3Sthurlow (strcmp(buf, "nbns") == 0 || 395*4bff34e3Sthurlow strcmp(buf, "nbns_enable") == 0 || 396*4bff34e3Sthurlow strcmp(buf, "nbns_broadcast") == 0)) { 397*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 398*4bff34e3Sthurlow "option %s may not be set " 399*4bff34e3Sthurlow "in user .nsmbrc file\n"), buf); 400*4bff34e3Sthurlow next = buf; 401*4bff34e3Sthurlow state = stNewLine; 402*4bff34e3Sthurlow continue; 403*4bff34e3Sthurlow } 404*4bff34e3Sthurlow if (insecure_nsmbrc && (strcmp(buf, "password") == 0)) { 405*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 406*4bff34e3Sthurlow "Warning: .nsmbrc file not secure, " 407*4bff34e3Sthurlow "ignoring passwords\n")); 408*4bff34e3Sthurlow next = buf; 409*4bff34e3Sthurlow state = stNewLine; 410*4bff34e3Sthurlow continue; 411*4bff34e3Sthurlow } 412*4bff34e3Sthurlow rkp = rc_sect_addkey(rsp, buf, NULL); 413*4bff34e3Sthurlow next = buf; 414*4bff34e3Sthurlow state = stGetValue; 415*4bff34e3Sthurlow continue; 416*4bff34e3Sthurlow } 417*4bff34e3Sthurlow /* only stGetValue left */ 418*4bff34e3Sthurlow if (state != stGetValue) { 419*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 420*4bff34e3Sthurlow "Well, I can't parse file '%s'\n"), rcp->rf_name); 421*4bff34e3Sthurlow state = stSkipToEOL; 422*4bff34e3Sthurlow } 423*4bff34e3Sthurlow if (c != '\n') { 424*4bff34e3Sthurlow *next++ = c; 425*4bff34e3Sthurlow continue; 426*4bff34e3Sthurlow } 427*4bff34e3Sthurlow *next = 0; 428*4bff34e3Sthurlow set_value(rcp, rsp, rkp, buf); 429*4bff34e3Sthurlow state = stNewLine; 430*4bff34e3Sthurlow rkp = NULL; 431*4bff34e3Sthurlow } /* while */ 432*4bff34e3Sthurlow if (c == EOF && state == stGetValue) { 433*4bff34e3Sthurlow *next = 0; 434*4bff34e3Sthurlow set_value(rcp, rsp, rkp, buf); 435*4bff34e3Sthurlow } 436*4bff34e3Sthurlow } 437*4bff34e3Sthurlow 438*4bff34e3Sthurlow int 439*4bff34e3Sthurlow rc_getstringptr(struct rcfile *rcp, const char *section, const char *key, 440*4bff34e3Sthurlow char **dest) 441*4bff34e3Sthurlow { 442*4bff34e3Sthurlow struct rcsection *rsp; 443*4bff34e3Sthurlow struct rckey *rkp; 444*4bff34e3Sthurlow 445*4bff34e3Sthurlow *dest = NULL; 446*4bff34e3Sthurlow rsp = rc_findsect(rcp, section); 447*4bff34e3Sthurlow if (!rsp) 448*4bff34e3Sthurlow return (ENOENT); 449*4bff34e3Sthurlow rkp = rc_sect_findkey(rsp, key); 450*4bff34e3Sthurlow if (!rkp) 451*4bff34e3Sthurlow return (ENOENT); 452*4bff34e3Sthurlow *dest = rkp->rk_value; 453*4bff34e3Sthurlow return (0); 454*4bff34e3Sthurlow } 455*4bff34e3Sthurlow 456*4bff34e3Sthurlow int 457*4bff34e3Sthurlow rc_getstring(struct rcfile *rcp, const char *section, const char *key, 458*4bff34e3Sthurlow size_t maxlen, char *dest) 459*4bff34e3Sthurlow { 460*4bff34e3Sthurlow char *value; 461*4bff34e3Sthurlow int error; 462*4bff34e3Sthurlow 463*4bff34e3Sthurlow error = rc_getstringptr(rcp, section, key, &value); 464*4bff34e3Sthurlow if (error) 465*4bff34e3Sthurlow return (error); 466*4bff34e3Sthurlow if (strlen(value) >= maxlen) { 467*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 468*4bff34e3Sthurlow "line too long for key '%s' in section '%s', max = %d\n"), 469*4bff34e3Sthurlow key, section, maxlen); 470*4bff34e3Sthurlow return (EINVAL); 471*4bff34e3Sthurlow } 472*4bff34e3Sthurlow strcpy(dest, value); 473*4bff34e3Sthurlow return (0); 474*4bff34e3Sthurlow } 475*4bff34e3Sthurlow 476*4bff34e3Sthurlow int 477*4bff34e3Sthurlow rc_getint(struct rcfile *rcp, const char *section, const char *key, int *value) 478*4bff34e3Sthurlow { 479*4bff34e3Sthurlow struct rcsection *rsp; 480*4bff34e3Sthurlow struct rckey *rkp; 481*4bff34e3Sthurlow 482*4bff34e3Sthurlow rsp = rc_findsect(rcp, section); 483*4bff34e3Sthurlow if (!rsp) 484*4bff34e3Sthurlow return (ENOENT); 485*4bff34e3Sthurlow rkp = rc_sect_findkey(rsp, key); 486*4bff34e3Sthurlow if (!rkp) 487*4bff34e3Sthurlow return (ENOENT); 488*4bff34e3Sthurlow errno = 0; 489*4bff34e3Sthurlow *value = strtol(rkp->rk_value, NULL, 0); 490*4bff34e3Sthurlow if (errno) { 491*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 492*4bff34e3Sthurlow "invalid int value '%s' for key '%s' in section '%s'\n"), 493*4bff34e3Sthurlow rkp->rk_value, key, section); 494*4bff34e3Sthurlow return (errno); 495*4bff34e3Sthurlow } 496*4bff34e3Sthurlow return (0); 497*4bff34e3Sthurlow } 498*4bff34e3Sthurlow 499*4bff34e3Sthurlow /* 500*4bff34e3Sthurlow * 1,yes,true 501*4bff34e3Sthurlow * 0,no,false 502*4bff34e3Sthurlow */ 503*4bff34e3Sthurlow int 504*4bff34e3Sthurlow rc_getbool(struct rcfile *rcp, const char *section, const char *key, int *value) 505*4bff34e3Sthurlow { 506*4bff34e3Sthurlow struct rcsection *rsp; 507*4bff34e3Sthurlow struct rckey *rkp; 508*4bff34e3Sthurlow char *p; 509*4bff34e3Sthurlow 510*4bff34e3Sthurlow rsp = rc_findsect(rcp, section); 511*4bff34e3Sthurlow if (!rsp) 512*4bff34e3Sthurlow return (ENOENT); 513*4bff34e3Sthurlow rkp = rc_sect_findkey(rsp, key); 514*4bff34e3Sthurlow if (!rkp) 515*4bff34e3Sthurlow return (ENOENT); 516*4bff34e3Sthurlow p = rkp->rk_value; 517*4bff34e3Sthurlow while (*p && isspace(*p)) p++; 518*4bff34e3Sthurlow if (*p == '0' || 519*4bff34e3Sthurlow strcasecmp(p, "no") == 0 || 520*4bff34e3Sthurlow strcasecmp(p, "false") == 0) { 521*4bff34e3Sthurlow *value = 0; 522*4bff34e3Sthurlow return (0); 523*4bff34e3Sthurlow } 524*4bff34e3Sthurlow if (*p == '1' || 525*4bff34e3Sthurlow strcasecmp(p, "yes") == 0 || 526*4bff34e3Sthurlow strcasecmp(p, "true") == 0) { 527*4bff34e3Sthurlow *value = 1; 528*4bff34e3Sthurlow return (0); 529*4bff34e3Sthurlow } 530*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 531*4bff34e3Sthurlow "invalid boolean value '%s' for key '%s' in section '%s' \n"), 532*4bff34e3Sthurlow p, key, section); 533*4bff34e3Sthurlow return (EINVAL); 534*4bff34e3Sthurlow } 535*4bff34e3Sthurlow 536*4bff34e3Sthurlow /* 537*4bff34e3Sthurlow * Unified command line/rc file parser 538*4bff34e3Sthurlow */ 539*4bff34e3Sthurlow int 540*4bff34e3Sthurlow opt_args_parse(struct rcfile *rcp, struct opt_args *ap, const char *sect, 541*4bff34e3Sthurlow opt_callback_t *callback) 542*4bff34e3Sthurlow { 543*4bff34e3Sthurlow int len, error; 544*4bff34e3Sthurlow 545*4bff34e3Sthurlow for (; ap->opt; ap++) { 546*4bff34e3Sthurlow switch (ap->type) { 547*4bff34e3Sthurlow case OPTARG_STR: 548*4bff34e3Sthurlow if (rc_getstringptr(rcp, sect, ap->name, &ap->str) != 0) 549*4bff34e3Sthurlow break; 550*4bff34e3Sthurlow len = strlen(ap->str); 551*4bff34e3Sthurlow if (len > ap->ival) { 552*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 553*4bff34e3Sthurlow "rc: argument for option '%c' (%s) too long\n"), 554*4bff34e3Sthurlow ap->opt, ap->name); 555*4bff34e3Sthurlow return (EINVAL); 556*4bff34e3Sthurlow } 557*4bff34e3Sthurlow callback(ap); 558*4bff34e3Sthurlow break; 559*4bff34e3Sthurlow case OPTARG_BOOL: 560*4bff34e3Sthurlow error = rc_getbool(rcp, sect, ap->name, &ap->ival); 561*4bff34e3Sthurlow if (error == ENOENT) 562*4bff34e3Sthurlow break; 563*4bff34e3Sthurlow if (error) 564*4bff34e3Sthurlow return (EINVAL); 565*4bff34e3Sthurlow callback(ap); 566*4bff34e3Sthurlow break; 567*4bff34e3Sthurlow case OPTARG_INT: 568*4bff34e3Sthurlow if (rc_getint(rcp, sect, ap->name, &ap->ival) != 0) 569*4bff34e3Sthurlow break; 570*4bff34e3Sthurlow if (((ap->flag & OPTFL_HAVEMIN) && 571*4bff34e3Sthurlow ap->ival < ap->min) || 572*4bff34e3Sthurlow ((ap->flag & OPTFL_HAVEMAX) && 573*4bff34e3Sthurlow ap->ival > ap->max)) { 574*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 575*4bff34e3Sthurlow "rc: argument for option '%c' (%s) " 576*4bff34e3Sthurlow "should be in [%d-%d] range\n"), 577*4bff34e3Sthurlow ap->opt, ap->name, ap->min, ap->max); 578*4bff34e3Sthurlow return (EINVAL); 579*4bff34e3Sthurlow } 580*4bff34e3Sthurlow callback(ap); 581*4bff34e3Sthurlow break; 582*4bff34e3Sthurlow default: 583*4bff34e3Sthurlow break; 584*4bff34e3Sthurlow } 585*4bff34e3Sthurlow } 586*4bff34e3Sthurlow return (0); 587*4bff34e3Sthurlow } 588*4bff34e3Sthurlow 589*4bff34e3Sthurlow int 590*4bff34e3Sthurlow opt_args_parseopt(struct opt_args *ap, int opt, char *arg, 591*4bff34e3Sthurlow opt_callback_t *callback) 592*4bff34e3Sthurlow { 593*4bff34e3Sthurlow int len; 594*4bff34e3Sthurlow 595*4bff34e3Sthurlow for (; ap->opt; ap++) { 596*4bff34e3Sthurlow if (ap->opt != opt) 597*4bff34e3Sthurlow continue; 598*4bff34e3Sthurlow switch (ap->type) { 599*4bff34e3Sthurlow case OPTARG_STR: 600*4bff34e3Sthurlow ap->str = arg; 601*4bff34e3Sthurlow if (arg) { 602*4bff34e3Sthurlow len = strlen(ap->str); 603*4bff34e3Sthurlow if (len > ap->ival) { 604*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 605*4bff34e3Sthurlow "opt: Argument for option '%c' (%s) too long\n"), 606*4bff34e3Sthurlow ap->opt, ap->name); 607*4bff34e3Sthurlow return (EINVAL); 608*4bff34e3Sthurlow } 609*4bff34e3Sthurlow callback(ap); 610*4bff34e3Sthurlow } 611*4bff34e3Sthurlow break; 612*4bff34e3Sthurlow case OPTARG_BOOL: 613*4bff34e3Sthurlow ap->ival = 0; 614*4bff34e3Sthurlow callback(ap); 615*4bff34e3Sthurlow break; 616*4bff34e3Sthurlow case OPTARG_INT: 617*4bff34e3Sthurlow errno = 0; 618*4bff34e3Sthurlow ap->ival = strtol(arg, NULL, 0); 619*4bff34e3Sthurlow if (errno) { 620*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 621*4bff34e3Sthurlow "opt: Invalid integer value for " 622*4bff34e3Sthurlow "option '%c' (%s).\n"), 623*4bff34e3Sthurlow ap->opt, ap->name); 624*4bff34e3Sthurlow return (EINVAL); 625*4bff34e3Sthurlow } 626*4bff34e3Sthurlow if (((ap->flag & OPTFL_HAVEMIN) && 627*4bff34e3Sthurlow (ap->ival < ap->min)) || 628*4bff34e3Sthurlow ((ap->flag & OPTFL_HAVEMAX) && 629*4bff34e3Sthurlow (ap->ival > ap->max))) { 630*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 631*4bff34e3Sthurlow "opt: Argument for option '%c' (%s) " 632*4bff34e3Sthurlow "should be in [%d-%d] range\n"), 633*4bff34e3Sthurlow ap->opt, ap->name, ap->min, ap->max); 634*4bff34e3Sthurlow return (EINVAL); 635*4bff34e3Sthurlow } 636*4bff34e3Sthurlow callback(ap); 637*4bff34e3Sthurlow break; 638*4bff34e3Sthurlow default: 639*4bff34e3Sthurlow break; 640*4bff34e3Sthurlow } 641*4bff34e3Sthurlow break; 642*4bff34e3Sthurlow } 643*4bff34e3Sthurlow return (0); 644*4bff34e3Sthurlow } 645