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