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