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