add more spacing
[personal-kdebase.git] / workspace / kdm / backend / inifile.c
blob16a0b70b76d5adcd6973d05e413ff91e7c5b3299
1 /*
3 Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of a copyright holder shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from the copyright holder.
30 * xdm - display manager daemon
31 * Author: Keith Packard, MIT X Consortium
33 * load, save and manipulate ini-style config files
36 #include "dm.h"
37 #include "dm_error.h"
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <fcntl.h>
46 char *
47 iniLoad( const char *fname )
49 char *data;
50 int fd, len;
51 struct stat st;
53 if ((fd = open( fname, O_RDONLY | O_NONBLOCK )) < 0) {
54 debug( "cannot open ini-file %\"s: %m", fname );
55 return 0;
57 if (fstat( fd, &st ) || !S_ISREG( st.st_mode )) {
58 logWarn( "Ini-file %\"s is no regular file\n", fname );
59 close( fd );
60 return 0;
62 if (st.st_size >= 0x10000) {
63 logWarn( "Ini-file %\"s is too big\n", fname );
64 close( fd );
65 return 0;
67 len = st.st_size;
68 if (!(data = Malloc( len + 2 ))) {
69 close( fd );
70 return 0;
72 if (read( fd, data, len ) != len) {
73 debug( "cannot read ini-file %\"s: %m", fname );
74 free( data );
75 close( fd );
76 return 0;
78 close( fd );
79 if (data[len - 1] != '\n') /* iniEntry() needs this. */
80 data[len++] = '\n';
81 data[len] = 0;
82 return data;
85 int
86 iniSave( const char *data, const char *fname )
88 int fd, cnt, len;
90 if ((fd = open( fname, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0600 )) < 0) {
91 debug( "cannot create ini-file %\"s: %m", fname );
92 return False;
94 len = strlen( data );
95 if ((cnt = write( fd, data, len )) == len) {
96 close( fd );
97 return True;
99 if (cnt == -1)
100 debug( "cannot write ini-file %\"s: %m", fname );
101 else
102 debug( "cannot write ini-file %\"s: partial write", fname );
103 close( fd );
104 return False;
107 #define apparr(d,s,n) do { memcpy (d, s, n); d += n; } while(0)
108 #define appbyte(d,b) *d++ = b
111 * NOTE: this relies on the last line being \n-terminated - if it is not,
112 * it will read past the end of the buffer!
114 char *
115 iniEntry( char *data, const char *section, const char *key, const char *value )
117 char *p = data, *secinsert = 0, *pastinsert = 0, *cb, *ce, *ndata;
118 const char *t;
119 int insect = False, ll, sl, kl, vl, len, nlen;
121 if (p) {
122 while (*p) {
123 for (; *p == ' ' || *p == '\t'; p++);
124 if (*p == '\n') {
125 /* Empty line, so don't advance insertion point. */
126 p++;
127 continue;
129 if (*p == '[') {
130 for (t = section; *++p == *t; t++);
131 insect = !*t && *p == ']';
132 } else if (insect) {
133 for (t = key; *p == *t; t++, p++);
134 for (; *p == ' ' || *p == '\t'; p++);
135 if (!*t && *p == '=') {
136 for (p++; *p == ' ' || *p == '\t'; p++);
137 cb = p;
138 while (*p++ != '\n');
139 ce = p;
140 if (value) {
141 ll = sl = kl = 0;
142 len = (ce - data) + strlen( ce );
143 goto insert;
144 } else {
145 for (ce--; ce != cb && (*(ce - 1) == ' ' || *(ce - 1) == '\t'); ce--);
146 if (!strNDup( &p, cb, ce - cb ))
147 return 0;
148 return p;
152 while (*p++ != '\n');
153 if (insect)
154 secinsert = p;
155 else
156 pastinsert = p;
159 if (!value)
160 return 0;
161 len = p - data;
162 if (secinsert) {
163 ce = cb = secinsert;
164 sl = ll = 0;
165 } else {
166 sl = strlen( section ) + 3;
167 if (pastinsert) {
168 ce = cb = pastinsert;
169 ll = 1;
170 } else {
171 ce = cb = data;
172 ll = 0;
175 kl = strlen( key ) + 1;
176 insert:
177 vl = strlen( value );
178 nlen = len - (ce - cb) + ll + sl + kl + vl + 1;
179 if (!(p = ndata = Malloc( nlen + 1 )))
180 return data;
181 apparr( p, data, cb - data ); /* zero length if data is null */
182 if (kl) {
183 if (sl) {
184 if (ll)
185 appbyte( p, '\n' );
186 appbyte( p, '[' );
187 apparr( p, section, sl - 3 );
188 appbyte( p, ']' );
189 appbyte( p, '\n' );
191 apparr( p, key, kl - 1 );
192 appbyte( p, '=' );
194 apparr( p, value, vl );
195 appbyte( p, '\n' );
196 if (data) {
197 apparr( p, ce, len - (ce - data) );
198 free( data );
200 appbyte( p, 0 );
201 return ndata;
204 char *
205 iniMerge( char *data, const char *newdata )
207 const char *p, *cb, *ce;
208 char *section = 0, *key, *value;
210 if (!newdata)
211 return data;
212 for (p = newdata;;) {
213 for (; *p == ' ' || *p == '\t'; p++);
214 if (!*p)
215 break;
216 if (*p == '\n') {
217 p++;
218 continue;
220 if (*p == '#') {
221 for (p++; *p != '\n'; p++)
222 if (!*p)
223 goto bail;
224 p++;
225 continue;
227 if (*p == '[') {
228 cb = ++p;
229 for (; *p != ']'; p++)
230 if (!*p || *p == '\n') /* missing ] */
231 goto bail;
232 if (!reStrN( &section, cb, p - cb ))
233 break;
234 p++;
235 } else {
236 cb = p;
237 for (; *p != '='; p++)
238 if (!*p || *p == '\n') /* missing = */
239 goto bail;
240 for (ce = p; ce != cb && (*(ce - 1) == ' ' || *(ce - 1) == '\t'); ce--);
241 if (!strNDup( &key, cb, ce - cb ))
242 break;
243 for (p++; *p == ' ' || *p == '\t'; p++);
244 cb = p;
245 for (; *p && *p != '\n'; p++);
246 for (ce = p; ce != cb && (*(ce - 1) == ' ' || *(ce - 1) == '\t'); ce--);
247 if (!strNDup( &value, cb, ce - cb ))
248 break;
249 if (section)
250 data = iniEntry( data, section, key, value );
251 free( value );
252 free( key );
255 bail:
256 if (section)
257 free( section );
258 return data;