2 * Copyright (c) 1999, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/types.h>
34 #include <sys/queue.h>
43 #include <netncp/ncp_lib.h>
44 #include <netncp/ncp_rcfile.h>
45 #include <netncp/ncp_cfg.h>
47 #define NWFS_CFG_FILE NCP_PREFIX"/etc/nwfs.conf"
49 struct rcfile
*ncp_rc
= NULL
;
51 SLIST_HEAD(rcfile_head
, rcfile
);
52 static struct rcfile_head pf_head
= {NULL
};
54 int rc_merge(char *filename
,struct rcfile
**rcfile
);
55 static struct rcfile
* rc_find(char *filename
);
56 static struct rcsection
*rc_findsect(struct rcfile
*rcp
, char *sectname
);
57 static struct rcsection
*rc_addsect(struct rcfile
*rcp
, char *sectname
);
58 static int rc_sect_free(struct rcsection
*rsp
);
59 static struct rckey
*rc_sect_findkey(struct rcsection
*rsp
, char *keyname
);
60 static struct rckey
*rc_sect_addkey(struct rcsection
*rsp
, char *name
, char *value
);
61 static void rc_key_free(struct rckey
*p
);
62 static void rc_parse(struct rcfile
*rcp
);
66 * open rcfile and load its content, if already open - return previous handle
69 rc_open(char *filename
,char *mode
,struct rcfile
**rcfile
) {
73 rcp
= rc_find(filename
);
78 f
= fopen (filename
, mode
);
81 rcp
= malloc(sizeof(struct rcfile
));
86 bzero(rcp
, sizeof(struct rcfile
));
87 rcp
->rf_name
= strdup (filename
);
89 SLIST_INSERT_HEAD(&pf_head
, rcp
, rf_next
);
96 rc_merge(char *filename
,struct rcfile
**rcfile
) {
97 struct rcfile
*rcp
= *rcfile
;
101 return rc_open(filename
,"r",rcfile
);
103 f
= fopen (filename
, "r");
115 rc_close(struct rcfile
*rcp
) {
116 struct rcsection
*p
,*n
;
119 for(p
= SLIST_FIRST(&rcp
->rf_sect
);p
;) {
121 p
= SLIST_NEXT(p
,rs_next
);
125 SLIST_REMOVE(&pf_head
, rcp
, rcfile
, rf_next
);
130 static struct rcfile
*
131 rc_find(char *filename
) {
134 SLIST_FOREACH(p
, &pf_head
, rf_next
)
135 if (strcmp (filename
, p
->rf_name
)==0)
140 static struct rcsection
*
141 rc_findsect(struct rcfile
*rcp
, char *sectname
) {
144 SLIST_FOREACH(p
, &rcp
->rf_sect
, rs_next
)
145 if (strcmp(p
->rs_name
, sectname
)==0)
150 static struct rcsection
*
151 rc_addsect(struct rcfile
*rcp
, char *sectname
) {
154 p
= rc_findsect(rcp
, sectname
);
156 p
= malloc(sizeof(*p
));
158 p
->rs_name
= strdup(sectname
);
159 SLIST_INIT(&p
->rs_keys
);
160 SLIST_INSERT_HEAD(&rcp
->rf_sect
, p
, rs_next
);
165 rc_sect_free(struct rcsection
*rsp
) {
168 for(p
= SLIST_FIRST(&rsp
->rs_keys
);p
;) {
170 p
= SLIST_NEXT(p
,rk_next
);
178 static struct rckey
*
179 rc_sect_findkey(struct rcsection
*rsp
, char *keyname
) {
182 SLIST_FOREACH(p
, &rsp
->rs_keys
, rk_next
)
183 if (strcmp(p
->rk_name
, keyname
)==0)
188 static struct rckey
*
189 rc_sect_addkey(struct rcsection
*rsp
, char *name
, char *value
) {
192 p
= rc_sect_findkey(rsp
, name
);
196 p
= malloc(sizeof(*p
));
198 SLIST_INSERT_HEAD(&rsp
->rs_keys
, p
, rk_next
);
199 p
->rk_name
= strdup(name
);
201 p
->rk_value
= value
? strdup(value
) : strdup("");
206 rc_sect_delkey(struct rcsection
*rsp
, struct rckey
*p
) {
208 SLIST_REMOVE(&rsp
->rs_keys
,p
,rckey
,rk_next
);
214 rc_key_free(struct rckey
*p
){
220 enum { stNewLine
, stHeader
, stSkipToEOL
, stGetKey
, stGetValue
};
223 rc_parse(struct rcfile
*rcp
) {
225 int state
= stNewLine
, c
;
226 struct rcsection
*rsp
= NULL
;
227 struct rckey
*rkp
= NULL
;
229 char *next
= buf
, *last
= &buf
[sizeof(buf
)-1];
231 while ((c
= getc (f
)) != EOF
) {
234 if (state
== stNewLine
) {
237 continue; /* skip leading junk */
243 if (c
== '#' || c
== ';') {
245 } else { /* something meaningfull */
249 if (state
== stSkipToEOL
|| next
== last
) {/* ignore long lines */
256 if (state
== stHeader
) {
260 rsp
= rc_addsect(rcp
, buf
);
266 if (state
== stGetKey
) {
267 if (c
== ' ' || c
== '\t')/* side effect: 'key name='*/
268 continue; /* become 'keyname=' */
269 if (c
== '\n') { /* silently ignore ... */
279 fprintf(stderr
, "Key '%s' defined before section\n", buf
);
283 rkp
= rc_sect_addkey(rsp
, buf
, NULL
);
288 /* only stGetValue left */
289 if (state
!= stGetValue
) {
290 fprintf(stderr
, "Well, I can't parse file '%s'\n",rcp
->rf_name
);
298 rkp
->rk_value
= strdup(buf
);
302 if (c
== EOF
&& state
== stGetValue
) {
304 rkp
->rk_value
= strdup(buf
);
310 rc_getstringptr(struct rcfile
*rcp
,char *section
, char *key
,char **dest
) {
311 struct rcsection
*rsp
;
315 rsp
= rc_findsect(rcp
, section
);
316 if (!rsp
) return ENOENT
;
317 rkp
= rc_sect_findkey(rsp
,key
);
318 if (!rkp
) return ENOENT
;
319 *dest
= rkp
->rk_value
;
324 rc_getstring(struct rcfile
*rcp
,char *section
, char *key
,int maxlen
,char *dest
) {
328 error
= rc_getstringptr(rcp
, section
, key
, &value
);
329 if (error
) return error
;
330 if (strlen(value
) >= maxlen
) {
331 fprintf(stderr
, "line too long for key '%s' in section '%s', max = %d\n",key
, section
, maxlen
);
339 rc_getint(struct rcfile
*rcp
,char *section
, char *key
,int *value
) {
340 struct rcsection
*rsp
;
343 rsp
= rc_findsect(rcp
, section
);
344 if (!rsp
) return ENOENT
;
345 rkp
= rc_sect_findkey(rsp
,key
);
346 if (!rkp
) return ENOENT
;
348 *value
= strtol(rkp
->rk_value
,NULL
,0);
350 fprintf(stderr
, "invalid int value '%s' for key '%s' in section '%s'\n",rkp
->rk_value
,key
,section
);
361 rc_getbool(struct rcfile
*rcp
,char *section
, char *key
,int *value
) {
362 struct rcsection
*rsp
;
366 rsp
= rc_findsect(rcp
, section
);
367 if (!rsp
) return ENOENT
;
368 rkp
= rc_sect_findkey(rsp
,key
);
369 if (!rkp
) return ENOENT
;
371 while (*p
&& isspace(*p
)) p
++;
372 if (*p
== '0' || strcasecmp(p
,"no") == 0 || strcasecmp(p
,"false") == 0) {
376 if (*p
== '1' || strcasecmp(p
,"yes") == 0 || strcasecmp(p
,"true") == 0) {
380 fprintf(stderr
, "invalid boolean value '%s' for key '%s' in section '%s' \n",p
, key
, section
);
385 * first read ~/.nwfsrc, next try to merge NWFS_CFG_FILE
388 ncp_open_rcfile(void) {
392 home
= getenv("HOME");
394 fn
= malloc(strlen(home
) + 20);
395 sprintf(fn
, "%s/.nwfsrc", home
);
396 error
= rc_open(fn
,"r",&ncp_rc
);
399 error
= rc_merge(NWFS_CFG_FILE
, &ncp_rc
);
400 if( ncp_rc
== NULL
) {
401 printf("Warning: no cfg files found.\n");