Fixed bugs list:
[unix-history] / lib / libutil / config.c
CommitLineData
7d4e84b3
JH
1/*
2 * Copyright (c) 1983,1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$Id$";
36#endif /* LIBC_SCCS and not lint */
37
38/*
39 * This file contains four procedures to read config-files with.
40 *
41 * char * config_open(const char *filename,int contlines)
42 * Will open the named file, and read it into a private malloced area,
43 * and close the file again. If contlines are non-zero
44 * continuation-lines will be allowed. In case of trouble, the name
45 * of the system-call causing the trouble will be returned. On success
46 * NULL is returned.
47 *
48 * void config_close()
49 * This will free the internal malloced area.
50 *
51 * char * config_next()
52 * This will return a pointer to the next entry in the area. NULL is
53 * returned at "end of file". If continuation-lines are used, the '\n'
54 * will be converted to ' '. The return value is '\0' terminated, and
55 * can be modified, but the contents must be copied somewhere else.
56 *
57 * char * config_skip(char **p)
58 * This will pick out the next word from the string. The return-value
59 * points to the word found, and *p is advanced past the word. NULL is
60 * returned at "end of string".
61 *
62 * The point about this is, that many programs have an n*100 bytes config-file
63 * and some N*1000 bytes of source to read it. Doing pointer-aerobics on
64 * files that small is waste of time, and bashing around with getchar/ungetc
65 * isn't much better. These routines implement a simple algorithm and syntax.
66 *
67 * 1. Lines starting in '#' are comments.
68 * 2. An entry starts with the first '!isspace()' character found.
69 * 3. If continuation-lines are enabled, an entry ends before the first
70 * empty line or before the first line not starting in an 'isspace()'
71 * character, whichever comes first.
72 * 4. Otherwise, an entry ends at the first '\n'.
73 *
74 * For config_skip goes that it considers a word as a contiguous string of
75 * !isspace() characters.
76 *
77 * There is an #ifdef'ed main() at the end, which is provided for test and
78 * illustration of use.
79 *
80 * 11jan1994 Poul-Henning Kamp phk@login.dkuug.dk
81 */
82
83#include <sys/types.h>
84#include <sys/stat.h>
85#include <stdlib.h>
86#include <fcntl.h>
87#include <unistd.h>
88#include <ctype.h>
89#include <string.h>
90
91static char * file_buf;
92static char * ptr;
93static int clines;
94
95char *
96config_open(const char *filename, int contlines)
97{
98 int fd;
99 struct stat st;
100
101 clines = contlines;
102 if((fd = open(filename,O_RDONLY)) < 0)
103 return "open";
104 if(fstat(fd,&st) < 0) {
105 close(fd);
106 return "fstat";
107 }
108 if(file_buf)
109 free(file_buf);
110 file_buf = malloc(st.st_size+1);
111 if(!file_buf) {
112 close(fd);
113 return "malloc";
114 }
115 if(st.st_size != read(fd,file_buf,st.st_size)) {
116 free(file_buf);
117 file_buf = (char*)0;
118 close(fd);
119 return "read";
120 }
121 close(fd);
122 file_buf[st.st_size] = '\0';
123 ptr = file_buf;
124 return 0;
125}
126
127void
128config_close(void)
129{
130 if(file_buf)
131 free(file_buf);
132 ptr = file_buf = 0;
133}
134
135/*
136 * Get next entry. An entry starts in column 0, and not with a '#',
137 * following lines are joined, if they start with white-space.
138 */
139char *
140config_next(void)
141{
142 char *p,*q;
143
144 /* We might be done already ! */
145 if(!ptr || !*ptr)
146 return 0;
147
148 /* Skip comments and blank lines */
149 while(*ptr) {
150 if(*ptr == '#') {
151 ptr = strchr(ptr,'\n');
152 if(!ptr)
153 return 0;
154 ptr++;
155 continue;
156 }
157 for(q=ptr;*q != '\n' && isspace(*q);q++) ;
158 if(*q != '\n')
159 break;
160 ptr = q+1;
161 }
162
163 if(!*ptr)
164 return 0;
165
166 p = ptr;
167 while(1) {
168 ptr = strchr(ptr,'\n');
169 if(!ptr) /* last line ? */
170 return p;
171 if(clines && isspace(ptr[1])) {
172 for(q=ptr+1;*q != '\n' && isspace(*q);q++) ;
173 if(*q != '\n') {
174 *ptr++ = ' ';
175 continue;
176 }
177 }
178 *ptr++ = '\0';
179 return p;
180 }
181}
182
183/*
184 * return next word
185 */
186
187char *
188config_skip(char **p)
189{
190 char *q,*r;
191
192 if(!*p || !**p)
193 return 0;
194 for(q = *p;isspace(*q);q++) ;
195 if(!*q)
196 return 0;
197 for(r=q;*r && !isspace(*r);r++) ;
198 if(*r)
199 *r++ = '\0';
200 *p = r;
201 return q;
202}