Remove include/local.h and move defines to more appropriate places.
[kai/samba.git] / source4 / param / generic.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Copyright (C) Jelmer Vernooij                       2005
4  *  
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 3 of the License, or
8  *  (at your option) any later version.
9  *  
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *  
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include "includes.h"
20 #include "../lib/util/dlinklist.h"
21 #include "param/param.h"
22 #include "system/filesys.h"
23
24 struct param_section *param_get_section(struct param_context *ctx, const char *name)
25 {
26         struct param_section *sect;
27
28         if (name == NULL) 
29                 name = GLOBAL_NAME;
30
31         for (sect = ctx->sections; sect; sect = sect->next) {
32                 if (!strcasecmp_m(sect->name, name)) 
33                         return sect;
34         }
35
36         return NULL;
37 }
38
39 struct param_opt *param_section_get(struct param_section *section, 
40                                     const char *name)
41 {
42         struct param_opt *p;
43
44         for (p = section->parameters; p; p = p->next) {
45                 if (strcasecmp_m(p->key, name) == 0) 
46                         return p;
47         }
48
49         return NULL;
50 }
51
52 struct param_opt *param_get (struct param_context *ctx, const char *name, const char *section_name)
53 {
54         struct param_section *section = param_get_section(ctx, section_name);
55         if (section == NULL)
56                 return NULL;
57
58         return param_section_get(section, name);
59 }
60
61 struct param_section *param_add_section(struct param_context *ctx, const char *section_name)
62 {
63         struct param_section *section;
64         section = talloc_zero(ctx, struct param_section);
65         if (section == NULL)
66                 return NULL;
67
68         section->name = talloc_strdup(section, section_name);
69         DLIST_ADD_END(ctx->sections, section, struct param_section *);
70         return section;
71 }
72
73 /* Look up parameter. If it is not found, add it */
74 struct param_opt *param_get_add(struct param_context *ctx, const char *name, const char *section_name)
75 {
76         struct param_section *section;
77         struct param_opt *p;
78
79         SMB_ASSERT(section_name != NULL);
80         SMB_ASSERT(name != NULL);
81
82         section = param_get_section(ctx, section_name);
83
84         if (section == NULL) {
85                 section = param_add_section(ctx, section_name);
86         }
87
88         p = param_section_get(section, name);
89         if (p == NULL) {
90                 p = talloc_zero(section, struct param_opt);
91                 if (p == NULL)
92                         return NULL;
93
94                 p->key = talloc_strdup(p, name);
95                 DLIST_ADD_END(section->parameters, p, struct param_opt *);
96         }
97         
98         return p;
99 }
100
101 const char *param_get_string(struct param_context *ctx, const char *param, const char *section)
102 {
103         struct param_opt *p = param_get(ctx, param, section);
104
105         if (p == NULL)
106                 return NULL;
107
108         return p->value;
109 }
110
111 int param_set_string(struct param_context *ctx, const char *param, const char *value, const char *section)
112 {
113         struct param_opt *p = param_get_add(ctx, param, section);
114
115         if (p == NULL)
116                 return -1;
117
118         p->value = talloc_strdup(p, value);
119
120         return 0;
121 }
122
123 const char **param_get_string_list(struct param_context *ctx, const char *param, const char *separator, const char *section)
124 {
125         struct param_opt *p = param_get(ctx, param, section);
126         
127         if (p == NULL)
128                 return NULL;
129
130         return (const char **)str_list_make(ctx, p->value, separator);
131 }
132
133 int param_set_string_list(struct param_context *ctx, const char *param, const char **list, const char *section)
134 {
135         struct param_opt *p = param_get_add(ctx, param, section);       
136
137         p->value = str_list_join(p, list, ' ');
138
139         return 0;
140 }
141
142 int param_get_int(struct param_context *ctx, const char *param, int default_v, const char *section)
143 {
144         const char *value = param_get_string(ctx, param, section);
145         
146         if (value)
147                 return strtol(value, NULL, 0); 
148
149         return default_v;
150 }
151
152 void param_set_int(struct param_context *ctx, const char *param, int value, const char *section)
153 {
154         struct param_opt *p = param_get_add(ctx, section, param);
155
156         if (!p) 
157                 return;
158
159         p->value = talloc_asprintf(p, "%d", value);
160 }
161
162 unsigned long param_get_ulong(struct param_context *ctx, const char *param, unsigned long default_v, const char *section)
163 {
164         const char *value = param_get_string(ctx, param, section);
165         
166         if (value)
167                 return strtoul(value, NULL, 0);
168
169         return default_v;
170 }
171
172 void param_set_ulong(struct param_context *ctx, const char *name, unsigned long value, const char *section)
173 {
174         struct param_opt *p = param_get_add(ctx, name, section);
175
176         if (!p)
177                 return;
178
179         p->value = talloc_asprintf(p, "%lu", value);
180 }
181
182 static bool param_sfunc (const char *name, void *_ctx)
183 {
184         struct param_context *ctx = (struct param_context *)_ctx;
185         struct param_section *section = param_get_section(ctx, name);
186
187         if (section == NULL) {
188                 section = talloc_zero(ctx, struct param_section);
189                 if (section == NULL)
190                         return false;
191
192                 section->name = talloc_strdup(section, name);
193
194                 DLIST_ADD_END(ctx->sections, section, struct param_section *);
195         }
196
197         /* Make sure this section is on top of the list for param_pfunc */
198         DLIST_PROMOTE(ctx->sections, section);
199
200         return true;
201 }
202
203 static bool param_pfunc (const char *name, const char *value, void *_ctx)
204 {
205         struct param_context *ctx = (struct param_context *)_ctx;
206         struct param_opt *p = param_section_get(ctx->sections, name);
207
208         if (!p) {
209                 p = talloc_zero(ctx->sections, struct param_opt);
210                 if (p == NULL)
211                         return false;
212
213                 p->key = talloc_strdup(p, name);
214                 p->value = talloc_strdup(p, value);
215                 DLIST_ADD(ctx->sections->parameters, p);
216         } else { /* Replace current value */
217                 talloc_free(p->value);
218                 p->value = talloc_strdup(p, value);
219         }
220
221         return true;
222 }
223
224 struct param_context *param_init(TALLOC_CTX *mem_ctx)
225 {
226         return talloc_zero(mem_ctx, struct param_context);
227 }
228
229
230 int param_read(struct param_context *ctx, const char *fn)
231 {
232         ctx->sections = talloc_zero(ctx, struct param_section);
233         if (ctx->sections == NULL)
234                 return -1;
235
236         ctx->sections->name = talloc_strdup(ctx->sections, "global");
237         if (!pm_process( fn, param_sfunc, param_pfunc, ctx)) {
238                 return -1;
239         }
240
241         return 0;
242 }
243
244 int param_use(struct loadparm_context *lp_ctx, struct param_context *ctx)
245 {
246         struct param_section *section;
247
248         for (section = ctx->sections; section; section = section->next) {
249                 struct param_opt *param;
250                 bool isglobal = strcmp(section->name, "global") == 0;
251                 for (param = section->parameters; param; param = param->next) {
252                         if (isglobal)
253                                 lp_do_global_parameter(lp_ctx, param->key,
254                                                        param->value);
255                         else {
256                                 struct loadparm_service *service = 
257                                                         lp_service(lp_ctx, section->name);
258                                 if (service == NULL)
259                                         service = lp_add_service(lp_ctx, lp_default_service(lp_ctx), section->name);
260                                 lp_do_service_parameter(lp_ctx, service, param->key, param->value);
261                         }
262                 }
263         }
264         return 0;
265 }
266
267 int param_write(struct param_context *ctx, const char *fn)
268 {
269         int file;
270         struct param_section *section;
271
272         if (fn == NULL || ctx == NULL)
273                 return -1;
274
275         file = open(fn, O_WRONLY|O_CREAT, 0755);
276
277         if (file == -1)
278                 return -1;
279         
280         for (section = ctx->sections; section; section = section->next) {
281                 struct param_opt *param;
282                 
283                 fdprintf(file, "[%s]\n", section->name);
284                 for (param = section->parameters; param; param = param->next) {
285                         fdprintf(file, "\t%s = %s\n", param->key, param->value);
286                 }
287                 fdprintf(file, "\n");
288         }
289
290         close(file);
291
292         return 0;
293 }