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