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