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