Tweaked some whitespace to match the latest version from autoconf.
[rsync/rsync.git] / loadparm.c
CommitLineData
0b76cd63
AT
1/* This is based on loadparm.c from Samba, written by Andrew Tridgell
2 and Karl Auer */
3
3d2e458a
MP
4/* some fixes
5 *
4366275b 6 * Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
3d2e458a
MP
7 */
8
6464bdbe 9/*
0b76cd63
AT
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
6464bdbe 14
0b76cd63
AT
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
6464bdbe 19
0b76cd63
AT
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25/*
26 * Load parameters.
27 *
28 * This module provides suitable callback functions for the params
29 * module. It builds the internal table of service details which is
30 * then used by the rest of the server.
31 *
32 * To add a parameter:
33 *
34 * 1) add it to the global or service structure definition
35 * 2) add it to the parm_table
36 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
37 * 4) If it's a global then initialise it in init_globals. If a local
38 * (ie. service) parameter then initialise it in the sDefault structure
6464bdbe 39 *
0b76cd63
AT
40 *
41 * Notes:
42 * The configuration file is processed sequentially for speed. It is NOT
43 * accessed randomly as happens in 'real' Windows. For this reason, there
44 * is a fair bit of sequence-dependent code here - ie., code which assumes
45 * that certain things happen before others. In particular, the code which
46 * happens at the boundary between sections is delicately poised, so be
47 * careful!
48 *
49 */
50
94f34ca1
MP
51/* TODO: Parameter to set debug level on server. */
52
0b76cd63 53#include "rsync.h"
0b76cd63
AT
54#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
55#define strequal(a,b) (strcasecmp(a,b)==0)
56#define BOOLSTR(b) ((b) ? "Yes" : "No")
57typedef char pstring[1024];
37f9805d 58#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
0b76cd63
AT
59
60/* the following are used by loadparm for option lists */
61typedef enum
62{
31593dd6 63 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
459a83c9 64 P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
0b76cd63
AT
65} parm_type;
66
67typedef enum
68{
31593dd6 69 P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
0b76cd63
AT
70} parm_class;
71
72struct enum_list {
73 int value;
74 char *name;
75};
76
77struct parm_struct
78{
79 char *label;
80 parm_type type;
81 parm_class class;
82 void *ptr;
83 struct enum_list *enum_list;
84 unsigned flags;
85};
86
0b76cd63
AT
87#ifndef GLOBAL_NAME
88#define GLOBAL_NAME "global"
89#endif
90
91/* some helpful bits */
92#define pSERVICE(i) ServicePtrs[i]
93#define iSERVICE(i) (*pSERVICE(i))
94#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
95
6464bdbe 96/*
0b76cd63
AT
97 * This structure describes global (ie., server-wide) parameters.
98 */
99typedef struct
100{
d17c9a44 101 char *bind_address;
4f6325c3 102 char *log_file;
d17c9a44 103 char *motd_file;
8638dd48 104 char *pid_file;
a6801c39 105 char *socket_options;
d17c9a44 106
0c56b1ad 107 int rsync_port;
d17c9a44 108 int syslog_facility;
0b76cd63
AT
109} global;
110
111static global Globals;
112
113
6464bdbe 114/*
d17c9a44
WD
115 * This structure describes a single service. Their order must match the
116 * initializers below, which you can accomplish by keeping each sub-section
e0a18ce3 117 * sorted. (e.g. in vim, just visually select each subsection and use !sort.)
0b76cd63
AT
118 */
119typedef struct
120{
d17c9a44 121 char *auth_users;
0b76cd63 122 char *comment;
d17c9a44
WD
123 char *dont_compress;
124 char *exclude;
125 char *exclude_from;
126 char *filter;
8ef4ffd6 127 char *gid;
56c473b7
AT
128 char *hosts_allow;
129 char *hosts_deny;
cd64343a
DD
130 char *include;
131 char *include_from;
882d8c1c 132 char *incoming_chmod;
d17c9a44 133 char *lock_file;
e08bfe12 134 char *log_format;
d17c9a44 135 char *name;
aaccaa88 136 char *outgoing_chmod;
d17c9a44 137 char *path;
bec617b9 138 char *postxfer_exec;
d17c9a44
WD
139 char *prexfer_exec;
140 char *refuse_options;
141 char *secrets_file;
18cad449 142 char *temp_dir;
d17c9a44
WD
143 char *uid;
144
5e71c444 145 int max_connections;
59b0e7a8 146 int max_verbosity;
d17c9a44
WD
147 int timeout;
148
149 BOOL ignore_errors;
60cb2f90 150 BOOL ignore_nonreadable;
d17c9a44
WD
151 BOOL list;
152 BOOL read_only;
153 BOOL strict_modes;
154 BOOL transfer_logging;
155 BOOL use_chroot;
156 BOOL write_only;
0b76cd63
AT
157} service;
158
159
e0a18ce3
WD
160/* This is a default service used to prime a services structure. In order
161 * to make these easy to keep sorted in the same way as the variables
162 * above, use the variable name in the leading comment, including a
163 * trailing ';' (to avoid a sorting problem with trailing digits). */
6464bdbe 164static service sDefault =
0b76cd63 165{
e0a18ce3
WD
166 /* auth_users; */ NULL,
167 /* comment; */ NULL,
168 /* dont_compress; */ "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",
169 /* exclude; */ NULL,
170 /* exclude_from; */ NULL,
171 /* filter; */ NULL,
172 /* gid; */ NOBODY_GROUP,
173 /* hosts_allow; */ NULL,
174 /* hosts_deny; */ NULL,
175 /* include; */ NULL,
176 /* include_from; */ NULL,
882d8c1c 177 /* incoming_chmod; */ NULL,
e0a18ce3
WD
178 /* lock_file; */ DEFAULT_LOCK_FILE,
179 /* log_format; */ "%o %h [%a] %m (%u) %f %l",
180 /* name; */ NULL,
aaccaa88 181 /* outgoing_chmod; */ NULL,
e0a18ce3
WD
182 /* path; */ NULL,
183 /* postxfer_exec; */ NULL,
184 /* prexfer_exec; */ NULL,
185 /* refuse_options; */ NULL,
186 /* secrets_file; */ NULL,
187 /* temp_dir; */ NULL,
188 /* uid; */ NOBODY_USER,
189
190 /* max_connections; */ 0,
191 /* max_verbosity; */ 1,
192 /* timeout; */ 0,
193
194 /* ignore_errors; */ False,
195 /* ignore_nonreadable; */ False,
196 /* list; */ True,
197 /* read_only; */ True,
198 /* strict_modes; */ True,
199 /* transfer_logging; */ False,
200 /* use_chroot; */ True,
201 /* write_only; */ False,
0b76cd63
AT
202};
203
204
205
206/* local variables */
207static service **ServicePtrs = NULL;
208static int iNumServices = 0;
209static int iServiceIndex = 0;
210static BOOL bInGlobalSection = True;
211
212#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
213
09e13ae2
AT
214static struct enum_list enum_facilities[] = {
215#ifdef LOG_AUTH
216 { LOG_AUTH, "auth" },
217#endif
218#ifdef LOG_AUTHPRIV
219 { LOG_AUTHPRIV, "authpriv" },
220#endif
221#ifdef LOG_CRON
222 { LOG_CRON, "cron" },
223#endif
224#ifdef LOG_DAEMON
225 { LOG_DAEMON, "daemon" },
226#endif
227#ifdef LOG_FTP
228 { LOG_FTP, "ftp" },
229#endif
230#ifdef LOG_KERN
231 { LOG_KERN, "kern" },
232#endif
233#ifdef LOG_LPR
234 { LOG_LPR, "lpr" },
235#endif
236#ifdef LOG_MAIL
237 { LOG_MAIL, "mail" },
238#endif
239#ifdef LOG_NEWS
240 { LOG_NEWS, "news" },
241#endif
242#ifdef LOG_AUTH
6464bdbe 243 { LOG_AUTH, "security" },
09e13ae2
AT
244#endif
245#ifdef LOG_SYSLOG
246 { LOG_SYSLOG, "syslog" },
247#endif
248#ifdef LOG_USER
249 { LOG_USER, "user" },
250#endif
251#ifdef LOG_UUCP
252 { LOG_UUCP, "uucp" },
253#endif
254#ifdef LOG_LOCAL0
255 { LOG_LOCAL0, "local0" },
256#endif
257#ifdef LOG_LOCAL1
258 { LOG_LOCAL1, "local1" },
259#endif
260#ifdef LOG_LOCAL2
261 { LOG_LOCAL2, "local2" },
262#endif
263#ifdef LOG_LOCAL3
264 { LOG_LOCAL3, "local3" },
265#endif
266#ifdef LOG_LOCAL4
267 { LOG_LOCAL4, "local4" },
268#endif
269#ifdef LOG_LOCAL5
270 { LOG_LOCAL5, "local5" },
271#endif
272#ifdef LOG_LOCAL6
273 { LOG_LOCAL6, "local6" },
274#endif
275#ifdef LOG_LOCAL7
276 { LOG_LOCAL7, "local7" },
277#endif
278 { -1, NULL }};
279
0b76cd63
AT
280
281/* note that we do not initialise the defaults union - it is not allowed in ANSI C */
282static struct parm_struct parm_table[] =
283{
d17c9a44
WD
284 {"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
285 {"log file", P_STRING, P_GLOBAL,&Globals.log_file, NULL,0},
286 {"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
287 {"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
288 {"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
289 {"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
290 {"syslog facility", P_ENUM, P_GLOBAL,&Globals.syslog_facility,enum_facilities,0},
291
292 {"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
293 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
294 {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
295 {"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
296 {"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
297 {"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
298 {"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
299 {"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
300 {"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL,0},
301 {"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors, NULL,0},
302 {"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable,NULL,0},
303 {"include from", P_STRING, P_LOCAL, &sDefault.include_from, NULL,0},
304 {"include", P_STRING, P_LOCAL, &sDefault.include, NULL,0},
882d8c1c 305 {"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
d17c9a44
WD
306 {"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
307 {"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
308 {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
309 {"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
310 {"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
311 {"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
aaccaa88 312 {"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
d17c9a44 313 {"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
bec617b9 314#ifdef HAVE_PUTENV
d17c9a44
WD
315 {"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec, NULL,0},
316 {"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL,0},
bec617b9 317#endif
d17c9a44
WD
318 {"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL,0},
319 {"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
320 {"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
321 {"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
18cad449 322 {"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
d17c9a44
WD
323 {"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
324 {"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
325 {"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL,0},
326 {"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL,0},
327 {"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL,0},
328 {NULL, P_BOOL, P_NONE, NULL, NULL,0}
0b76cd63
AT
329};
330
331
332/***************************************************************************
333Initialise the global parameter structure.
334***************************************************************************/
335static void init_globals(void)
336{
46f7dc3b 337 memset(&Globals, 0, sizeof Globals);
851dbdb7
AT
338#ifdef LOG_DAEMON
339 Globals.syslog_facility = LOG_DAEMON;
340#endif
0b76cd63
AT
341}
342
343/***************************************************************************
344Initialise the sDefault parameter structure.
345***************************************************************************/
346static void init_locals(void)
347{
348}
349
350
351/*
6464bdbe
WD
352 In this section all the functions that are used to access the
353 parameters from the rest of the program are defined
0b76cd63
AT
354*/
355
356#define FN_GLOBAL_STRING(fn_name,ptr) \
357 char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
358#define FN_GLOBAL_BOOL(fn_name,ptr) \
359 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
360#define FN_GLOBAL_CHAR(fn_name,ptr) \
361 char fn_name(void) {return(*(char *)(ptr));}
362#define FN_GLOBAL_INTEGER(fn_name,ptr) \
363 int fn_name(void) {return(*(int *)(ptr));}
364
365#define FN_LOCAL_STRING(fn_name,val) \
366 char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
367#define FN_LOCAL_BOOL(fn_name,val) \
368 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
369#define FN_LOCAL_CHAR(fn_name,val) \
370 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
371#define FN_LOCAL_INTEGER(fn_name,val) \
372 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
373
374
d17c9a44 375FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
4f6325c3 376FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
d17c9a44 377FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
8638dd48 378FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
a6801c39 379FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
d17c9a44 380
0c56b1ad 381FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
d17c9a44 382FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
a6801c39 383
d17c9a44 384FN_LOCAL_STRING(lp_auth_users, auth_users)
0b76cd63 385FN_LOCAL_STRING(lp_comment, comment)
d17c9a44
WD
386FN_LOCAL_STRING(lp_dont_compress, dont_compress)
387FN_LOCAL_STRING(lp_exclude, exclude)
388FN_LOCAL_STRING(lp_exclude_from, exclude_from)
389FN_LOCAL_STRING(lp_filter, filter)
8ef4ffd6 390FN_LOCAL_STRING(lp_gid, gid)
56c473b7
AT
391FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
392FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
cd64343a
DD
393FN_LOCAL_STRING(lp_include, include)
394FN_LOCAL_STRING(lp_include_from, include_from)
882d8c1c 395FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
d17c9a44 396FN_LOCAL_STRING(lp_lock_file, lock_file)
e08bfe12 397FN_LOCAL_STRING(lp_log_format, log_format)
d17c9a44 398FN_LOCAL_STRING(lp_name, name)
aaccaa88 399FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
d17c9a44 400FN_LOCAL_STRING(lp_path, path)
bec617b9 401FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
d17c9a44
WD
402FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
403FN_LOCAL_STRING(lp_refuse_options, refuse_options)
404FN_LOCAL_STRING(lp_secrets_file, secrets_file)
18cad449 405FN_LOCAL_STRING(lp_temp_dir, temp_dir)
d17c9a44
WD
406FN_LOCAL_STRING(lp_uid, uid)
407
5e71c444 408FN_LOCAL_INTEGER(lp_max_connections, max_connections)
59b0e7a8 409FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
d17c9a44
WD
410FN_LOCAL_INTEGER(lp_timeout, timeout)
411
412FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
413FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
414FN_LOCAL_BOOL(lp_list, list)
415FN_LOCAL_BOOL(lp_read_only, read_only)
416FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
417FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
418FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
419FN_LOCAL_BOOL(lp_write_only, write_only)
0b76cd63
AT
420
421/* local prototypes */
6464bdbe
WD
422static int strwicmp(char *psz1, char *psz2);
423static int map_parameter(char *parmname);
424static BOOL set_boolean(BOOL *pb, char *parmvalue);
0b76cd63 425static int getservicebyname(char *name, service *pserviceDest);
6464bdbe 426static void copy_service(service *pserviceDest, service *pserviceSource);
0b76cd63
AT
427static BOOL do_parameter(char *parmname, char *parmvalue);
428static BOOL do_section(char *sectionname);
429
430
431/***************************************************************************
432initialise a service to the defaults
433***************************************************************************/
434static void init_service(service *pservice)
435{
f5780433 436 memset((char *)pservice,0,sizeof(service));
45ccc5c0 437 copy_service(pservice,&sDefault);
0b76cd63
AT
438}
439
3d2e458a
MP
440
441/**
1179355d
MP
442 * Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
443 * be initialized when this is called, either to NULL or a malloc'd
444 * string.
445 *
446 * @fixme There is a small leak here in that sometimes the existing
447 * value will be dynamically allocated, and the old copy is lost.
448 * However, we can't always deallocate the old value, because in the
449 * case of sDefault, it points to a static string. It would be nice
450 * to have either all-strdup'd values, or to never need to free
451 * memory.
3d2e458a
MP
452 **/
453static void string_set(char **s, const char *v)
0b76cd63 454{
0b76cd63
AT
455 if (!v) {
456 *s = NULL;
457 return;
458 }
459 *s = strdup(v);
3d2e458a
MP
460 if (!*s)
461 exit_cleanup(RERR_MALLOC);
0b76cd63
AT
462}
463
464
465/***************************************************************************
6464bdbe 466add a new service to the services array initialising it with the given
0b76cd63
AT
467service
468***************************************************************************/
469static int add_a_service(service *pservice, char *name)
470{
471 int i;
472 service tservice;
473 int num_to_alloc = iNumServices+1;
474
475 tservice = *pservice;
476
477 /* it might already exist */
6464bdbe 478 if (name)
0b76cd63
AT
479 {
480 i = getservicebyname(name,NULL);
481 if (i >= 0)
482 return(i);
483 }
484
485 i = iNumServices;
486
58cadc86 487 ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
6cdc6b13 488
0b76cd63 489 if (ServicePtrs)
58cadc86 490 pSERVICE(iNumServices) = new(service);
0b76cd63
AT
491
492 if (!ServicePtrs || !pSERVICE(iNumServices))
493 return(-1);
494
495 iNumServices++;
496
497 init_service(pSERVICE(i));
498 copy_service(pSERVICE(i),&tservice);
499 if (name)
6464bdbe 500 string_set(&iSERVICE(i).name,name);
0b76cd63
AT
501
502 return(i);
503}
504
505/***************************************************************************
506Do a case-insensitive, whitespace-ignoring string compare.
507***************************************************************************/
508static int strwicmp(char *psz1, char *psz2)
509{
510 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
511 /* appropriate value. */
512 if (psz1 == psz2)
513 return (0);
514 else
515 if (psz1 == NULL)
516 return (-1);
517 else
518 if (psz2 == NULL)
519 return (1);
520
521 /* sync the strings on first non-whitespace */
522 while (1)
523 {
32f76175 524 while (isspace(* (unsigned char *) psz1))
0b76cd63 525 psz1++;
32f76175 526 while (isspace(* (unsigned char *) psz2))
0b76cd63 527 psz2++;
32f76175 528 if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
3e8369b6 529 || *psz1 == '\0' || *psz2 == '\0')
0b76cd63
AT
530 break;
531 psz1++;
532 psz2++;
533 }
534 return (*psz1 - *psz2);
535}
536
537/***************************************************************************
6464bdbe 538Map a parameter's string representation to something we can use.
0b76cd63
AT
539Returns False if the parameter string is not recognised, else TRUE.
540***************************************************************************/
541static int map_parameter(char *parmname)
542{
543 int iIndex;
544
545 if (*parmname == '-')
546 return(-1);
547
6464bdbe 548 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
0b76cd63
AT
549 if (strwicmp(parm_table[iIndex].label, parmname) == 0)
550 return(iIndex);
551
cd64343a 552 rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
0b76cd63
AT
553 return(-1);
554}
555
556
557/***************************************************************************
558Set a boolean variable from the text value stored in the passed string.
6464bdbe 559Returns True in success, False if the passed string does not correctly
0b76cd63
AT
560represent a boolean.
561***************************************************************************/
562static BOOL set_boolean(BOOL *pb, char *parmvalue)
563{
564 BOOL bRetval;
565
566 bRetval = True;
567 if (strwicmp(parmvalue, "yes") == 0 ||
568 strwicmp(parmvalue, "true") == 0 ||
569 strwicmp(parmvalue, "1") == 0)
570 *pb = True;
571 else
572 if (strwicmp(parmvalue, "no") == 0 ||
573 strwicmp(parmvalue, "False") == 0 ||
574 strwicmp(parmvalue, "0") == 0)
575 *pb = False;
576 else
577 {
578 rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
579 parmvalue);
580 bRetval = False;
581 }
582 return (bRetval);
583}
584
585/***************************************************************************
586Find a service by name. Otherwise works like get_service.
587***************************************************************************/
588static int getservicebyname(char *name, service *pserviceDest)
589{
590 int iService;
591
592 for (iService = iNumServices - 1; iService >= 0; iService--)
6464bdbe 593 if (strwicmp(iSERVICE(iService).name, name) == 0)
0b76cd63
AT
594 {
595 if (pserviceDest != NULL)
596 copy_service(pserviceDest, pSERVICE(iService));
597 break;
598 }
599
600 return (iService);
601}
602
603
604
605/***************************************************************************
606Copy a service structure to another
607
608***************************************************************************/
6464bdbe 609static void copy_service(service *pserviceDest,
0b76cd63
AT
610 service *pserviceSource)
611{
612 int i;
613
614 for (i=0;parm_table[i].label;i++)
615 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
616 void *def_ptr = parm_table[i].ptr;
6464bdbe 617 void *src_ptr =
0b76cd63 618 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
6464bdbe 619 void *dest_ptr =
0b76cd63
AT
620 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
621
622 switch (parm_table[i].type)
623 {
624 case P_BOOL:
625 case P_BOOLREV:
626 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
627 break;
628
629 case P_INTEGER:
630 case P_ENUM:
631 case P_OCTAL:
632 *(int *)dest_ptr = *(int *)src_ptr;
633 break;
634
635 case P_CHAR:
636 *(char *)dest_ptr = *(char *)src_ptr;
637 break;
638
459a83c9 639 case P_PATH:
0b76cd63
AT
640 case P_STRING:
641 string_set(dest_ptr,*(char **)src_ptr);
642 break;
643
644 default:
645 break;
646 }
647 }
648}
649
650
651/***************************************************************************
652Process a parameter for a particular service number. If snum < 0
653then assume we are in the globals
654***************************************************************************/
655static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
656{
657 int parmnum, i;
658 void *parm_ptr=NULL; /* where we are going to store the result */
659 void *def_ptr=NULL;
459a83c9 660 char *cp;
0b76cd63
AT
661
662 parmnum = map_parameter(parmname);
663
664 if (parmnum < 0)
665 {
cd64343a 666 rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
0b76cd63
AT
667 return(True);
668 }
669
670 def_ptr = parm_table[parmnum].ptr;
671
672 /* we might point at a service, the default service or a global */
673 if (snum < 0) {
674 parm_ptr = def_ptr;
675 } else {
676 if (parm_table[parmnum].class == P_GLOBAL) {
677 rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
678 return(True);
679 }
680 parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
681 }
682
683 /* now switch on the type of variable it is */
684 switch (parm_table[parmnum].type)
685 {
686 case P_BOOL:
687 set_boolean(parm_ptr,parmvalue);
688 break;
689
690 case P_BOOLREV:
691 set_boolean(parm_ptr,parmvalue);
692 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
693 break;
694
695 case P_INTEGER:
696 *(int *)parm_ptr = atoi(parmvalue);
697 break;
698
699 case P_CHAR:
700 *(char *)parm_ptr = *parmvalue;
701 break;
702
703 case P_OCTAL:
704 sscanf(parmvalue,"%o",(int *)parm_ptr);
705 break;
706
459a83c9
WD
707 case P_PATH:
708 string_set(parm_ptr,parmvalue);
709 if ((cp = *(char**)parm_ptr) != NULL) {
710 int len = strlen(cp);
15089022
WD
711 while (len > 1 && cp[len-1] == '/') len--;
712 cp[len] = '\0';
459a83c9
WD
713 }
714 break;
715
0b76cd63
AT
716 case P_STRING:
717 string_set(parm_ptr,parmvalue);
718 break;
719
720 case P_GSTRING:
37f9805d 721 strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring));
0b76cd63
AT
722 break;
723
724 case P_ENUM:
725 for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
726 if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
727 *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
728 break;
729 }
730 }
fabf5ea7 731 if (!parm_table[parmnum].enum_list[i].name) {
41059f75
AT
732 if (atoi(parmvalue) > 0)
733 *(int *)parm_ptr = atoi(parmvalue);
fabf5ea7 734 }
0b76cd63
AT
735 break;
736 case P_SEP:
737 break;
738 }
739
740 return(True);
741}
742
743/***************************************************************************
744Process a parameter.
745***************************************************************************/
746static BOOL do_parameter(char *parmname, char *parmvalue)
747{
748 return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
749}
750
751/***************************************************************************
752Process a new section (service). At this stage all sections are services.
753Later we'll have special sections that permit server parameters to be set.
754Returns True on success, False on failure.
755***************************************************************************/
756static BOOL do_section(char *sectionname)
757{
758 BOOL bRetval;
759 BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
760 bRetval = False;
761
762 /* if we were in a global section then do the local inits */
763 if (bInGlobalSection && !isglobal)
764 init_locals();
765
766 /* if we've just struck a global section, note the fact. */
6464bdbe 767 bInGlobalSection = isglobal;
0b76cd63
AT
768
769 /* check for multiple global sections */
770 if (bInGlobalSection)
771 {
772 return(True);
773 }
774
775 /* if we have a current service, tidy it up before moving on */
776 bRetval = True;
777
778 if (iServiceIndex >= 0)
779 bRetval = True;
780
781 /* if all is still well, move to the next record in the services array */
782 if (bRetval)
783 {
784 /* We put this here to avoid an odd message order if messages are */
785 /* issued by the post-processing of a previous section. */
786
787 if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
788 {
789 rprintf(FERROR,"Failed to add a new service\n");
790 return(False);
791 }
792 }
793
794 return (bRetval);
795}
796
797
798/***************************************************************************
6464bdbe 799Load the services array from the services file. Return True on success,
0b76cd63
AT
800False on failure.
801***************************************************************************/
f9e940ef 802BOOL lp_load(char *pszFname, int globals_only)
0b76cd63 803{
30e8c8e1 804 extern int am_server;
30e8c8e1 805 extern int am_root;
f9e940ef
AT
806 pstring n2;
807 BOOL bRetval;
6464bdbe 808
f9e940ef 809 bRetval = False;
0b76cd63 810
f9e940ef 811 bInGlobalSection = True;
6464bdbe 812
f9e940ef 813 init_globals();
0b76cd63 814
30e8c8e1
DD
815 if (pszFname)
816 pstrcpy(n2,pszFname);
077d5d4e 817 else if (am_server && !am_root)
30e8c8e1
DD
818 pstrcpy(n2,RSYNCD_USERCONF);
819 else
820 pstrcpy(n2,RSYNCD_SYSCONF);
0b76cd63 821
f9e940ef
AT
822 /* We get sections first, so have to start 'behind' to make up */
823 iServiceIndex = -1;
824 bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
6464bdbe 825
f9e940ef 826 return (bRetval);
0b76cd63
AT
827}
828
829
830/***************************************************************************
831return the max number of services
832***************************************************************************/
833int lp_numservices(void)
834{
835 return(iNumServices);
836}
837
838/***************************************************************************
839Return the number of the service with the given name, or -1 if it doesn't
840exist. Note that this is a DIFFERENT ANIMAL from the internal function
841getservicebyname()! This works ONLY if all services have been loaded, and
842does not copy the found service.
843***************************************************************************/
844int lp_number(char *name)
845{
846 int iService;
847
848 for (iService = iNumServices - 1; iService >= 0; iService--)
8b6ad019 849 if (strcmp(lp_name(iService), name) == 0)
0b76cd63
AT
850 break;
851
852 return (iService);
853}
854