Added RERR_VANISHED.
[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;
851dbdb7 104 int syslog_facility;
a6801c39 105 char *socket_options;
0b76cd63
AT
106} global;
107
108static global Globals;
109
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},
41059f75 271
81791cfc 272 {"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
5e71c444 273 {"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
0b76cd63
AT
274 {"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
275 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
5e71c444 276 {"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
459a83c9 277 {"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
0b76cd63
AT
278 {"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
279 {"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
8638dd48 280 {"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
60cb2f90 281 {"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable, NULL, 0},
8ef4ffd6
AT
282 {"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
283 {"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
56c473b7
AT
284 {"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
285 {"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
31593dd6
AT
286 {"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
287 {"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
3ca8e68f 288 {"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes,NULL, 0},
8f3a2d54
AT
289 {"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
290 {"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
cd64343a
DD
291 {"include", P_STRING, P_LOCAL, &sDefault.include, NULL, 0},
292 {"include from", P_STRING, P_LOCAL, &sDefault.include_from,NULL, 0},
11a5a3c7 293 {"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
cda2ae84 294 {"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0},
e08bfe12 295 {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
cd8185f2 296 {"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0},
83fff1aa 297 {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0},
0b76cd63
AT
298 {NULL, P_BOOL, P_NONE, NULL, NULL, 0}
299};
300
301
302/***************************************************************************
303Initialise the global parameter structure.
304***************************************************************************/
305static void init_globals(void)
306{
f9e940ef 307 memset(&Globals, 0, sizeof(Globals));
851dbdb7
AT
308#ifdef LOG_DAEMON
309 Globals.syslog_facility = LOG_DAEMON;
310#endif
0b76cd63
AT
311}
312
313/***************************************************************************
314Initialise the sDefault parameter structure.
315***************************************************************************/
316static void init_locals(void)
317{
318}
319
320
321/*
6464bdbe
WD
322 In this section all the functions that are used to access the
323 parameters from the rest of the program are defined
0b76cd63
AT
324*/
325
326#define FN_GLOBAL_STRING(fn_name,ptr) \
327 char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
328#define FN_GLOBAL_BOOL(fn_name,ptr) \
329 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
330#define FN_GLOBAL_CHAR(fn_name,ptr) \
331 char fn_name(void) {return(*(char *)(ptr));}
332#define FN_GLOBAL_INTEGER(fn_name,ptr) \
333 int fn_name(void) {return(*(int *)(ptr));}
334
335#define FN_LOCAL_STRING(fn_name,val) \
336 char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
337#define FN_LOCAL_BOOL(fn_name,val) \
338 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
339#define FN_LOCAL_CHAR(fn_name,val) \
340 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
341#define FN_LOCAL_INTEGER(fn_name,val) \
342 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
343
344
345FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
4f6325c3 346FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
8638dd48 347FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
a6801c39 348FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
851dbdb7 349FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
a6801c39 350
0b76cd63
AT
351FN_LOCAL_STRING(lp_name, name)
352FN_LOCAL_STRING(lp_comment, comment)
353FN_LOCAL_STRING(lp_path, path)
5e71c444 354FN_LOCAL_STRING(lp_lock_file, lock_file)
0b76cd63
AT
355FN_LOCAL_BOOL(lp_read_only, read_only)
356FN_LOCAL_BOOL(lp_list, list)
8638dd48 357FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
11a5a3c7 358FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
cda2ae84 359FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
60cb2f90 360FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
8ef4ffd6
AT
361FN_LOCAL_STRING(lp_uid, uid)
362FN_LOCAL_STRING(lp_gid, gid)
56c473b7
AT
363FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
364FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
31593dd6
AT
365FN_LOCAL_STRING(lp_auth_users, auth_users)
366FN_LOCAL_STRING(lp_secrets_file, secrets_file)
3ca8e68f 367FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
8f3a2d54
AT
368FN_LOCAL_STRING(lp_exclude, exclude)
369FN_LOCAL_STRING(lp_exclude_from, exclude_from)
cd64343a
DD
370FN_LOCAL_STRING(lp_include, include)
371FN_LOCAL_STRING(lp_include_from, include_from)
e08bfe12 372FN_LOCAL_STRING(lp_log_format, log_format)
cd8185f2 373FN_LOCAL_STRING(lp_refuse_options, refuse_options)
83fff1aa 374FN_LOCAL_STRING(lp_dont_compress, dont_compress)
81791cfc 375FN_LOCAL_INTEGER(lp_timeout, timeout)
5e71c444 376FN_LOCAL_INTEGER(lp_max_connections, max_connections)
0b76cd63
AT
377
378/* local prototypes */
6464bdbe
WD
379static int strwicmp(char *psz1, char *psz2);
380static int map_parameter(char *parmname);
381static BOOL set_boolean(BOOL *pb, char *parmvalue);
0b76cd63 382static int getservicebyname(char *name, service *pserviceDest);
6464bdbe 383static void copy_service(service *pserviceDest, service *pserviceSource);
0b76cd63
AT
384static BOOL do_parameter(char *parmname, char *parmvalue);
385static BOOL do_section(char *sectionname);
386
387
388/***************************************************************************
389initialise a service to the defaults
390***************************************************************************/
391static void init_service(service *pservice)
392{
f5780433 393 memset((char *)pservice,0,sizeof(service));
45ccc5c0 394 copy_service(pservice,&sDefault);
0b76cd63
AT
395}
396
3d2e458a
MP
397
398/**
1179355d
MP
399 * Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
400 * be initialized when this is called, either to NULL or a malloc'd
401 * string.
402 *
403 * @fixme There is a small leak here in that sometimes the existing
404 * value will be dynamically allocated, and the old copy is lost.
405 * However, we can't always deallocate the old value, because in the
406 * case of sDefault, it points to a static string. It would be nice
407 * to have either all-strdup'd values, or to never need to free
408 * memory.
3d2e458a
MP
409 **/
410static void string_set(char **s, const char *v)
0b76cd63 411{
0b76cd63
AT
412 if (!v) {
413 *s = NULL;
414 return;
415 }
416 *s = strdup(v);
3d2e458a
MP
417 if (!*s)
418 exit_cleanup(RERR_MALLOC);
0b76cd63
AT
419}
420
421
422/***************************************************************************
6464bdbe 423add a new service to the services array initialising it with the given
0b76cd63
AT
424service
425***************************************************************************/
426static int add_a_service(service *pservice, char *name)
427{
428 int i;
429 service tservice;
430 int num_to_alloc = iNumServices+1;
431
432 tservice = *pservice;
433
434 /* it might already exist */
6464bdbe 435 if (name)
0b76cd63
AT
436 {
437 i = getservicebyname(name,NULL);
438 if (i >= 0)
439 return(i);
440 }
441
442 i = iNumServices;
443
58cadc86 444 ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
6cdc6b13 445
0b76cd63 446 if (ServicePtrs)
58cadc86 447 pSERVICE(iNumServices) = new(service);
0b76cd63
AT
448
449 if (!ServicePtrs || !pSERVICE(iNumServices))
450 return(-1);
451
452 iNumServices++;
453
454 init_service(pSERVICE(i));
455 copy_service(pSERVICE(i),&tservice);
456 if (name)
6464bdbe 457 string_set(&iSERVICE(i).name,name);
0b76cd63
AT
458
459 return(i);
460}
461
462/***************************************************************************
463Do a case-insensitive, whitespace-ignoring string compare.
464***************************************************************************/
465static int strwicmp(char *psz1, char *psz2)
466{
467 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
468 /* appropriate value. */
469 if (psz1 == psz2)
470 return (0);
471 else
472 if (psz1 == NULL)
473 return (-1);
474 else
475 if (psz2 == NULL)
476 return (1);
477
478 /* sync the strings on first non-whitespace */
479 while (1)
480 {
32f76175 481 while (isspace(* (unsigned char *) psz1))
0b76cd63 482 psz1++;
32f76175 483 while (isspace(* (unsigned char *) psz2))
0b76cd63 484 psz2++;
32f76175 485 if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
3e8369b6 486 || *psz1 == '\0' || *psz2 == '\0')
0b76cd63
AT
487 break;
488 psz1++;
489 psz2++;
490 }
491 return (*psz1 - *psz2);
492}
493
494/***************************************************************************
6464bdbe 495Map a parameter's string representation to something we can use.
0b76cd63
AT
496Returns False if the parameter string is not recognised, else TRUE.
497***************************************************************************/
498static int map_parameter(char *parmname)
499{
500 int iIndex;
501
502 if (*parmname == '-')
503 return(-1);
504
6464bdbe 505 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
0b76cd63
AT
506 if (strwicmp(parm_table[iIndex].label, parmname) == 0)
507 return(iIndex);
508
cd64343a 509 rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
0b76cd63
AT
510 return(-1);
511}
512
513
514/***************************************************************************
515Set a boolean variable from the text value stored in the passed string.
6464bdbe 516Returns True in success, False if the passed string does not correctly
0b76cd63
AT
517represent a boolean.
518***************************************************************************/
519static BOOL set_boolean(BOOL *pb, char *parmvalue)
520{
521 BOOL bRetval;
522
523 bRetval = True;
524 if (strwicmp(parmvalue, "yes") == 0 ||
525 strwicmp(parmvalue, "true") == 0 ||
526 strwicmp(parmvalue, "1") == 0)
527 *pb = True;
528 else
529 if (strwicmp(parmvalue, "no") == 0 ||
530 strwicmp(parmvalue, "False") == 0 ||
531 strwicmp(parmvalue, "0") == 0)
532 *pb = False;
533 else
534 {
535 rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
536 parmvalue);
537 bRetval = False;
538 }
539 return (bRetval);
540}
541
542/***************************************************************************
543Find a service by name. Otherwise works like get_service.
544***************************************************************************/
545static int getservicebyname(char *name, service *pserviceDest)
546{
547 int iService;
548
549 for (iService = iNumServices - 1; iService >= 0; iService--)
6464bdbe 550 if (strwicmp(iSERVICE(iService).name, name) == 0)
0b76cd63
AT
551 {
552 if (pserviceDest != NULL)
553 copy_service(pserviceDest, pSERVICE(iService));
554 break;
555 }
556
557 return (iService);
558}
559
560
561
562/***************************************************************************
563Copy a service structure to another
564
565***************************************************************************/
6464bdbe 566static void copy_service(service *pserviceDest,
0b76cd63
AT
567 service *pserviceSource)
568{
569 int i;
570
571 for (i=0;parm_table[i].label;i++)
572 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
573 void *def_ptr = parm_table[i].ptr;
6464bdbe 574 void *src_ptr =
0b76cd63 575 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
6464bdbe 576 void *dest_ptr =
0b76cd63
AT
577 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
578
579 switch (parm_table[i].type)
580 {
581 case P_BOOL:
582 case P_BOOLREV:
583 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
584 break;
585
586 case P_INTEGER:
587 case P_ENUM:
588 case P_OCTAL:
589 *(int *)dest_ptr = *(int *)src_ptr;
590 break;
591
592 case P_CHAR:
593 *(char *)dest_ptr = *(char *)src_ptr;
594 break;
595
459a83c9 596 case P_PATH:
0b76cd63
AT
597 case P_STRING:
598 string_set(dest_ptr,*(char **)src_ptr);
599 break;
600
601 default:
602 break;
603 }
604 }
605}
606
607
608/***************************************************************************
609Process a parameter for a particular service number. If snum < 0
610then assume we are in the globals
611***************************************************************************/
612static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
613{
614 int parmnum, i;
615 void *parm_ptr=NULL; /* where we are going to store the result */
616 void *def_ptr=NULL;
459a83c9 617 char *cp;
0b76cd63
AT
618
619 parmnum = map_parameter(parmname);
620
621 if (parmnum < 0)
622 {
cd64343a 623 rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
0b76cd63
AT
624 return(True);
625 }
626
627 def_ptr = parm_table[parmnum].ptr;
628
629 /* we might point at a service, the default service or a global */
630 if (snum < 0) {
631 parm_ptr = def_ptr;
632 } else {
633 if (parm_table[parmnum].class == P_GLOBAL) {
634 rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
635 return(True);
636 }
637 parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
638 }
639
640 /* now switch on the type of variable it is */
641 switch (parm_table[parmnum].type)
642 {
643 case P_BOOL:
644 set_boolean(parm_ptr,parmvalue);
645 break;
646
647 case P_BOOLREV:
648 set_boolean(parm_ptr,parmvalue);
649 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
650 break;
651
652 case P_INTEGER:
653 *(int *)parm_ptr = atoi(parmvalue);
654 break;
655
656 case P_CHAR:
657 *(char *)parm_ptr = *parmvalue;
658 break;
659
660 case P_OCTAL:
661 sscanf(parmvalue,"%o",(int *)parm_ptr);
662 break;
663
459a83c9
WD
664 case P_PATH:
665 string_set(parm_ptr,parmvalue);
666 if ((cp = *(char**)parm_ptr) != NULL) {
667 int len = strlen(cp);
15089022
WD
668 while (len > 1 && cp[len-1] == '/') len--;
669 cp[len] = '\0';
459a83c9
WD
670 }
671 break;
672
0b76cd63
AT
673 case P_STRING:
674 string_set(parm_ptr,parmvalue);
675 break;
676
677 case P_GSTRING:
37f9805d 678 strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring));
0b76cd63
AT
679 break;
680
681 case P_ENUM:
682 for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
683 if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
684 *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
685 break;
686 }
687 }
fabf5ea7 688 if (!parm_table[parmnum].enum_list[i].name) {
41059f75
AT
689 if (atoi(parmvalue) > 0)
690 *(int *)parm_ptr = atoi(parmvalue);
fabf5ea7 691 }
0b76cd63
AT
692 break;
693 case P_SEP:
694 break;
695 }
696
697 return(True);
698}
699
700/***************************************************************************
701Process a parameter.
702***************************************************************************/
703static BOOL do_parameter(char *parmname, char *parmvalue)
704{
705 return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
706}
707
708/***************************************************************************
709Process a new section (service). At this stage all sections are services.
710Later we'll have special sections that permit server parameters to be set.
711Returns True on success, False on failure.
712***************************************************************************/
713static BOOL do_section(char *sectionname)
714{
715 BOOL bRetval;
716 BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
717 bRetval = False;
718
719 /* if we were in a global section then do the local inits */
720 if (bInGlobalSection && !isglobal)
721 init_locals();
722
723 /* if we've just struck a global section, note the fact. */
6464bdbe 724 bInGlobalSection = isglobal;
0b76cd63
AT
725
726 /* check for multiple global sections */
727 if (bInGlobalSection)
728 {
729 return(True);
730 }
731
732 /* if we have a current service, tidy it up before moving on */
733 bRetval = True;
734
735 if (iServiceIndex >= 0)
736 bRetval = True;
737
738 /* if all is still well, move to the next record in the services array */
739 if (bRetval)
740 {
741 /* We put this here to avoid an odd message order if messages are */
742 /* issued by the post-processing of a previous section. */
743
744 if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
745 {
746 rprintf(FERROR,"Failed to add a new service\n");
747 return(False);
748 }
749 }
750
751 return (bRetval);
752}
753
754
755/***************************************************************************
6464bdbe 756Load the services array from the services file. Return True on success,
0b76cd63
AT
757False on failure.
758***************************************************************************/
f9e940ef 759BOOL lp_load(char *pszFname, int globals_only)
0b76cd63 760{
30e8c8e1
DD
761 extern int am_server;
762 extern int am_daemon;
763 extern int am_root;
f9e940ef
AT
764 pstring n2;
765 BOOL bRetval;
6464bdbe 766
f9e940ef 767 bRetval = False;
0b76cd63 768
f9e940ef 769 bInGlobalSection = True;
6464bdbe 770
f9e940ef 771 init_globals();
0b76cd63 772
30e8c8e1
DD
773 if (pszFname)
774 pstrcpy(n2,pszFname);
775 else if (am_server && am_daemon && !am_root)
776 pstrcpy(n2,RSYNCD_USERCONF);
777 else
778 pstrcpy(n2,RSYNCD_SYSCONF);
0b76cd63 779
f9e940ef
AT
780 /* We get sections first, so have to start 'behind' to make up */
781 iServiceIndex = -1;
782 bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
6464bdbe 783
f9e940ef 784 return (bRetval);
0b76cd63
AT
785}
786
787
788/***************************************************************************
789return the max number of services
790***************************************************************************/
791int lp_numservices(void)
792{
793 return(iNumServices);
794}
795
796/***************************************************************************
797Return the number of the service with the given name, or -1 if it doesn't
798exist. Note that this is a DIFFERENT ANIMAL from the internal function
799getservicebyname()! This works ONLY if all services have been loaded, and
800does not copy the found service.
801***************************************************************************/
802int lp_number(char *name)
803{
804 int iService;
805
806 for (iService = iNumServices - 1; iService >= 0; iService--)
6464bdbe 807 if (strequal(lp_name(iService), name))
0b76cd63
AT
808 break;
809
810 return (iService);
811}
812