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