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