summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/config.c
blob: ffe276697990fd1fd6853df6e4550b93fc64ca74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
 * ----------------------------------------------------------------------------
 *
 * $Id: config.c,v 1.1 1994/11/13 20:47:43 phk Exp $
 *
 */

#if defined(LIBC_SCCS) && !defined(lint)
static char rcsid[] = "$Id: config.c,v 1.1 1994/11/13 20:47:43 phk Exp $";
#endif				/* LIBC_SCCS and not lint */

/*
 * This file contains four procedures used to read config-files.
 *
 * char * config_open(const char *filename,int contlines)
 *	Will open the named file, read it into a private malloc'ed area,
 *	and close the file again.
 *	All lines where the first !isspace() char is '#' are deleted.
 *	If contlines are non-zero lines where the first char is isspace()
 *	will be joined to the preceeding line.
 *	In case of trouble the name of the offending system call will be
 *	returned.  On success NULL is returned.
 *
 * void   config_close()
 *	This will free the internal malloc'ed area.
 *
 * char * config_next()
 *	This will return a pointer to the next entry in the area.  NULL is
 *	returned at "end of file".  The return value is '\0' terminated, and
 *	can be modified, but the contents must be copied somewhere else for
 *	permanent use.
 *
 * char * config_skip(char **p)
 *	This will pick out the next word from the string.  The return-value
 *	points to the word found, and *p is advanced past the word.  NULL is
 *	returned at "end of string".
 *
 * Many programs have a n*100 bytes config-file and N*1000 bytes of source
 * to read it.  Doing pointer-aerobics on files that small is a waste of
 * time, and bashing around with getchar/ungetc isn't much better.  These
 * routines implement a simple algorithm and syntax.
 *
 * config_skip consider a contiguous string of !isspace() chars a word.
 *
 * 13nov1994 Poul-Henning Kamp  phk@login.dknet.dk
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>

static char *file_buf;
static char *ptr;

char   *
config_open(const char *filename, int contlines)
{
	int     fd;
	struct stat st;
	char   *p, *q;

	if ((fd = open(filename, O_RDONLY)) < 0)
		return "open";
	if (fstat(fd, &st) < 0) {
		close(fd);
		return "fstat";
	}
	if (file_buf)
		free(file_buf);
	file_buf = malloc(st.st_size + 2);
	if (!file_buf) {
		close(fd);
		return "malloc";
	}
	if (st.st_size != read(fd, file_buf, st.st_size)) {
		free(file_buf);
		file_buf = (char *) 0;
		close(fd);
		return "read";
	}
	close(fd);
	file_buf[st.st_size] = '\n';
	file_buf[st.st_size + 1] = '\0';

	/*
         * /^[ \t]*#[^\n]*$/d
	 *
	 * Delete all lines where the first !isspace() char is '#'
         */

	ptr = file_buf;
	for (p = ptr; *p;) {
		for (q = p; *q != '\n' && isspace(*q); q++)
			continue;
		if (*q == '#') {
			p = strchr(p, '\n');
			if (p)
				p++;
		} else {
			q = strchr(p, '\n');
			q++;
			memcpy(ptr, p, q - p);
			ptr += q - p;
			p = q;
		}
	}
	*ptr = '\0';
	ptr = file_buf;

	if (!contlines)
		return 0;

	/* Join all lines starting with a isspace() char to the preceeding
	 * line */

	for (p = ptr; *p;) {
		q = strchr(p, '\n');
		if (isspace(*(q + 1)))
			*q = ' ';
		p = q + 1;
	}

	return 0;
}

void
config_close(void)
{
	if (file_buf)
		free(file_buf);
	ptr = file_buf = 0;
}

/*
 * Get next entry.  config_open did all the weird stuff, so just return
 * the next line.
 */

char   *
config_next(void)
{
	char   *p;

	/* We might be done already ! */
	if (!ptr || !*ptr)
		return 0;

	while (isspace(*ptr))
	    ptr++;
	p = ptr;
	ptr = strchr(p, '\n');
	if (ptr) {
		*ptr = '\0';
		ptr++;
	}
	return p;
}

/*
 * Return next word
 */

char   *
config_skip(char **p)
{
	char   *q, *r;

	if (!*p || !**p)
		return 0;
	for (q = *p; isspace(*q); q++);
	if (!*q)
		return 0;
	for (r = q; *r && !isspace(*r); r++);
	if (*r)
		*r++ = '\0';
	*p = r;
	return q;
}
OpenPOWER on IntegriCloud