documentation!
[rsync/rsync.git] / loadparm.c
1 /* This is based on loadparm.c from Samba, written by Andrew Tridgell
2    and Karl Auer */
3
4 /* 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /*
21  *  Load parameters.
22  *
23  *  This module provides suitable callback functions for the params
24  *  module. It builds the internal table of service details which is
25  *  then used by the rest of the server.
26  *
27  * To add a parameter:
28  *
29  * 1) add it to the global or service structure definition
30  * 2) add it to the parm_table
31  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
32  * 4) If it's a global then initialise it in init_globals. If a local
33  *    (ie. service) parameter then initialise it in the sDefault structure
34  *  
35  *
36  * Notes:
37  *   The configuration file is processed sequentially for speed. It is NOT
38  *   accessed randomly as happens in 'real' Windows. For this reason, there
39  *   is a fair bit of sequence-dependent code here - ie., code which assumes
40  *   that certain things happen before others. In particular, the code which
41  *   happens at the boundary between sections is delicately poised, so be
42  *   careful!
43  *
44  */
45
46 #include "rsync.h"
47 #define BOOL int
48 #define False 0
49 #define True 1
50 #define Realloc realloc
51 #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
52 #define strequal(a,b) (strcasecmp(a,b)==0)
53 #define BOOLSTR(b) ((b) ? "Yes" : "No")
54 typedef char pstring[1024];
55 #define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring)-1)
56
57 /* the following are used by loadparm for option lists */
58 typedef enum
59 {
60         P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
61         P_STRING,P_GSTRING,P_ENUM,P_SEP
62 } parm_type;
63
64 typedef enum
65 {
66         P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
67 } parm_class;
68
69 struct enum_list {
70         int value;
71         char *name;
72 };
73
74 struct parm_struct
75 {
76         char *label;
77         parm_type type;
78         parm_class class;
79         void *ptr;
80         struct enum_list *enum_list;
81         unsigned flags;
82 };
83
84 static BOOL bLoaded = False;
85
86 #ifndef GLOBAL_NAME
87 #define GLOBAL_NAME "global"
88 #endif
89
90 /* some helpful bits */
91 #define pSERVICE(i) ServicePtrs[i]
92 #define iSERVICE(i) (*pSERVICE(i))
93 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
94
95 /* 
96  * This structure describes global (ie., server-wide) parameters.
97  */
98 typedef struct
99 {
100         char *motd_file;
101         char *lock_file;
102         int syslog_facility;
103         int max_connections;
104 } global;
105
106 static global Globals;
107
108
109
110 /* 
111  * This structure describes a single service. 
112  */
113 typedef struct
114 {
115         char *name;
116         char *path;
117         char *comment;
118         BOOL read_only;
119         BOOL list;
120         char *uid;
121         char *gid;
122         char *hosts_allow;
123         char *hosts_deny;
124         char *auth_users;
125         char *secrets_file;
126 } service;
127
128
129 /* This is a default service used to prime a services structure */
130 static service sDefault = 
131 {
132         NULL,    /* name */
133         NULL,    /* path */
134         NULL,    /* comment */
135         True,    /* read only */
136         True,    /* list */
137         "nobody",/* uid */
138         "nobody",/* gid */
139         NULL,    /* hosts allow */
140         NULL,    /* hosts deny */
141         NULL,    /* auth users */
142         NULL,    /* secrets file */
143 };
144
145
146
147 /* local variables */
148 static service **ServicePtrs = NULL;
149 static int iNumServices = 0;
150 static int iServiceIndex = 0;
151 static BOOL bInGlobalSection = True;
152
153 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
154
155 static struct enum_list enum_facilities[] = {
156 #ifdef LOG_AUTH
157         { LOG_AUTH, "auth" },
158 #endif
159 #ifdef LOG_AUTHPRIV
160         { LOG_AUTHPRIV, "authpriv" },
161 #endif
162 #ifdef LOG_CRON
163         { LOG_CRON, "cron" },
164 #endif
165 #ifdef LOG_DAEMON
166         { LOG_DAEMON, "daemon" },
167 #endif
168 #ifdef LOG_FTP
169         { LOG_FTP, "ftp" },
170 #endif
171 #ifdef LOG_KERN
172         { LOG_KERN, "kern" },
173 #endif
174 #ifdef LOG_LPR
175         { LOG_LPR, "lpr" },
176 #endif
177 #ifdef LOG_MAIL
178         { LOG_MAIL, "mail" },
179 #endif
180 #ifdef LOG_NEWS
181         { LOG_NEWS, "news" },
182 #endif
183 #ifdef LOG_AUTH
184         { LOG_AUTH, "security" },               
185 #endif
186 #ifdef LOG_SYSLOG
187         { LOG_SYSLOG, "syslog" },
188 #endif
189 #ifdef LOG_USER
190         { LOG_USER, "user" },
191 #endif
192 #ifdef LOG_UUCP
193         { LOG_UUCP, "uucp" },
194 #endif
195 #ifdef LOG_LOCAL0
196         { LOG_LOCAL0, "local0" },
197 #endif
198 #ifdef LOG_LOCAL1
199         { LOG_LOCAL1, "local1" },
200 #endif
201 #ifdef LOG_LOCAL2
202         { LOG_LOCAL2, "local2" },
203 #endif
204 #ifdef LOG_LOCAL3
205         { LOG_LOCAL3, "local3" },
206 #endif
207 #ifdef LOG_LOCAL4
208         { LOG_LOCAL4, "local4" },
209 #endif
210 #ifdef LOG_LOCAL5
211         { LOG_LOCAL5, "local5" },
212 #endif
213 #ifdef LOG_LOCAL6
214         { LOG_LOCAL6, "local6" },
215 #endif
216 #ifdef LOG_LOCAL7
217         { LOG_LOCAL7, "local7" },
218 #endif
219         { -1, NULL }};
220
221
222 /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
223 static struct parm_struct parm_table[] =
224 {
225   {"max connections",  P_INTEGER, P_GLOBAL, &Globals.max_connections,NULL, 0},
226   {"motd file",        P_STRING,  P_GLOBAL, &Globals.motd_file,    NULL,   0},
227   {"lock file",        P_STRING,  P_GLOBAL, &Globals.lock_file,    NULL,   0},
228   {"syslog facility",  P_ENUM,    P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
229
230   {"name",             P_STRING,  P_LOCAL,  &sDefault.name,        NULL,   0},
231   {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,     NULL,   0},
232   {"path",             P_STRING,  P_LOCAL,  &sDefault.path,        NULL,   0},
233   {"read only",        P_BOOL,    P_LOCAL,  &sDefault.read_only,   NULL,   0},
234   {"list",             P_BOOL,    P_LOCAL,  &sDefault.list,        NULL,   0},
235   {"uid",              P_STRING,  P_LOCAL,  &sDefault.uid,         NULL,   0},
236   {"gid",              P_STRING,  P_LOCAL,  &sDefault.gid,         NULL,   0},
237   {"hosts allow",      P_STRING,  P_LOCAL,  &sDefault.hosts_allow, NULL,   0},
238   {"hosts deny",       P_STRING,  P_LOCAL,  &sDefault.hosts_deny,  NULL,   0},
239   {"auth users",       P_STRING,  P_LOCAL,  &sDefault.auth_users,  NULL,   0},
240   {"secrets file",     P_STRING,  P_LOCAL,  &sDefault.secrets_file,NULL,   0},
241   {NULL,               P_BOOL,    P_NONE,   NULL,                  NULL,   0}
242 };
243
244
245 /***************************************************************************
246 Initialise the global parameter structure.
247 ***************************************************************************/
248 static void init_globals(void)
249 {
250 #ifdef LOG_DAEMON
251         Globals.syslog_facility = LOG_DAEMON;
252 #endif
253         Globals.lock_file = "/var/run/rsyncd.lock";
254 }
255
256 /***************************************************************************
257 Initialise the sDefault parameter structure.
258 ***************************************************************************/
259 static void init_locals(void)
260 {
261 }
262
263
264 /*
265    In this section all the functions that are used to access the 
266    parameters from the rest of the program are defined 
267 */
268
269 #define FN_GLOBAL_STRING(fn_name,ptr) \
270  char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
271 #define FN_GLOBAL_BOOL(fn_name,ptr) \
272  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
273 #define FN_GLOBAL_CHAR(fn_name,ptr) \
274  char fn_name(void) {return(*(char *)(ptr));}
275 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
276  int fn_name(void) {return(*(int *)(ptr));}
277
278 #define FN_LOCAL_STRING(fn_name,val) \
279  char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
280 #define FN_LOCAL_BOOL(fn_name,val) \
281  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
282 #define FN_LOCAL_CHAR(fn_name,val) \
283  char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
284 #define FN_LOCAL_INTEGER(fn_name,val) \
285  int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
286
287
288 FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
289 FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
290 FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
291 FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
292 FN_LOCAL_STRING(lp_name, name)
293 FN_LOCAL_STRING(lp_comment, comment)
294 FN_LOCAL_STRING(lp_path, path)
295 FN_LOCAL_BOOL(lp_read_only, read_only)
296 FN_LOCAL_BOOL(lp_list, list)
297 FN_LOCAL_STRING(lp_uid, uid)
298 FN_LOCAL_STRING(lp_gid, gid)
299 FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
300 FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
301 FN_LOCAL_STRING(lp_auth_users, auth_users)
302 FN_LOCAL_STRING(lp_secrets_file, secrets_file)
303
304 /* local prototypes */
305 static int    strwicmp( char *psz1, char *psz2 );
306 static int    map_parameter( char *parmname);
307 static BOOL   set_boolean( BOOL *pb, char *parmvalue );
308 static int    getservicebyname(char *name, service *pserviceDest);
309 static void   copy_service( service *pserviceDest, 
310                             service *pserviceSource);
311 static BOOL   do_parameter(char *parmname, char *parmvalue);
312 static BOOL   do_section(char *sectionname);
313
314
315 /***************************************************************************
316 initialise a service to the defaults
317 ***************************************************************************/
318 static void init_service(service *pservice)
319 {
320         bzero((char *)pservice,sizeof(service));
321         copy_service(pservice,&sDefault);
322 }
323
324 static void string_set(char **s, char *v)
325 {
326         if (!v) {
327                 *s = NULL;
328                 return;
329         }
330         *s = strdup(v);
331         if (!*s) exit_cleanup(1);
332 }
333
334
335 /***************************************************************************
336 add a new service to the services array initialising it with the given 
337 service
338 ***************************************************************************/
339 static int add_a_service(service *pservice, char *name)
340 {
341   int i;
342   service tservice;
343   int num_to_alloc = iNumServices+1;
344
345   tservice = *pservice;
346
347   /* it might already exist */
348   if (name) 
349     {
350       i = getservicebyname(name,NULL);
351       if (i >= 0)
352         return(i);
353     }
354
355   i = iNumServices;
356
357   ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
358   if (ServicePtrs)
359           pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
360
361   if (!ServicePtrs || !pSERVICE(iNumServices))
362           return(-1);
363
364   iNumServices++;
365
366   init_service(pSERVICE(i));
367   copy_service(pSERVICE(i),&tservice);
368   if (name)
369     string_set(&iSERVICE(i).name,name);  
370
371   return(i);
372 }
373
374 /***************************************************************************
375 Do a case-insensitive, whitespace-ignoring string compare.
376 ***************************************************************************/
377 static int strwicmp(char *psz1, char *psz2)
378 {
379    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
380    /* appropriate value. */
381    if (psz1 == psz2)
382       return (0);
383    else
384       if (psz1 == NULL)
385          return (-1);
386       else
387           if (psz2 == NULL)
388               return (1);
389
390    /* sync the strings on first non-whitespace */
391    while (1)
392    {
393       while (isspace(*psz1))
394          psz1++;
395       while (isspace(*psz2))
396          psz2++;
397       if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
398          break;
399       psz1++;
400       psz2++;
401    }
402    return (*psz1 - *psz2);
403 }
404
405 /***************************************************************************
406 Map a parameter's string representation to something we can use. 
407 Returns False if the parameter string is not recognised, else TRUE.
408 ***************************************************************************/
409 static int map_parameter(char *parmname)
410 {
411    int iIndex;
412
413    if (*parmname == '-')
414      return(-1);
415
416    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
417       if (strwicmp(parm_table[iIndex].label, parmname) == 0)
418          return(iIndex);
419
420    rprintf(FERROR, "Unknown parameter encountered: \"%s\"\n", parmname);
421    return(-1);
422 }
423
424
425 /***************************************************************************
426 Set a boolean variable from the text value stored in the passed string.
427 Returns True in success, False if the passed string does not correctly 
428 represent a boolean.
429 ***************************************************************************/
430 static BOOL set_boolean(BOOL *pb, char *parmvalue)
431 {
432    BOOL bRetval;
433
434    bRetval = True;
435    if (strwicmp(parmvalue, "yes") == 0 ||
436        strwicmp(parmvalue, "true") == 0 ||
437        strwicmp(parmvalue, "1") == 0)
438       *pb = True;
439    else
440       if (strwicmp(parmvalue, "no") == 0 ||
441           strwicmp(parmvalue, "False") == 0 ||
442           strwicmp(parmvalue, "0") == 0)
443          *pb = False;
444       else
445       {
446          rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
447                parmvalue);
448          bRetval = False;
449       }
450    return (bRetval);
451 }
452
453 /***************************************************************************
454 Find a service by name. Otherwise works like get_service.
455 ***************************************************************************/
456 static int getservicebyname(char *name, service *pserviceDest)
457 {
458    int iService;
459
460    for (iService = iNumServices - 1; iService >= 0; iService--)
461       if (strwicmp(iSERVICE(iService).name, name) == 0) 
462       {
463          if (pserviceDest != NULL)
464            copy_service(pserviceDest, pSERVICE(iService));
465          break;
466       }
467
468    return (iService);
469 }
470
471
472
473 /***************************************************************************
474 Copy a service structure to another
475
476 ***************************************************************************/
477 static void copy_service(service *pserviceDest, 
478                          service *pserviceSource)
479 {
480   int i;
481
482   for (i=0;parm_table[i].label;i++)
483     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
484         void *def_ptr = parm_table[i].ptr;
485         void *src_ptr = 
486           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
487         void *dest_ptr = 
488           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
489
490         switch (parm_table[i].type)
491           {
492           case P_BOOL:
493           case P_BOOLREV:
494             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
495             break;
496
497           case P_INTEGER:
498           case P_ENUM:
499           case P_OCTAL:
500             *(int *)dest_ptr = *(int *)src_ptr;
501             break;
502
503           case P_CHAR:
504             *(char *)dest_ptr = *(char *)src_ptr;
505             break;
506
507           case P_STRING:
508             string_set(dest_ptr,*(char **)src_ptr);
509             break;
510
511           default:
512             break;
513           }
514       }
515 }
516
517
518 /***************************************************************************
519 Process a parameter for a particular service number. If snum < 0
520 then assume we are in the globals
521 ***************************************************************************/
522 static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
523 {
524    int parmnum, i;
525    void *parm_ptr=NULL; /* where we are going to store the result */
526    void *def_ptr=NULL;
527
528    parmnum = map_parameter(parmname);
529
530    if (parmnum < 0)
531      {
532        rprintf(FERROR, "Ignoring unknown parameter \"%s\"\n", parmname);
533        return(True);
534      }
535
536    def_ptr = parm_table[parmnum].ptr;
537
538    /* we might point at a service, the default service or a global */
539    if (snum < 0) {
540      parm_ptr = def_ptr;
541    } else {
542        if (parm_table[parmnum].class == P_GLOBAL) {
543            rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
544            return(True);
545          }
546        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
547    }
548
549    /* now switch on the type of variable it is */
550    switch (parm_table[parmnum].type)
551      {
552      case P_BOOL:
553        set_boolean(parm_ptr,parmvalue);
554        break;
555
556      case P_BOOLREV:
557        set_boolean(parm_ptr,parmvalue);
558        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
559        break;
560
561      case P_INTEGER:
562        *(int *)parm_ptr = atoi(parmvalue);
563        break;
564
565      case P_CHAR:
566        *(char *)parm_ptr = *parmvalue;
567        break;
568
569      case P_OCTAL:
570        sscanf(parmvalue,"%o",(int *)parm_ptr);
571        break;
572
573      case P_STRING:
574        string_set(parm_ptr,parmvalue);
575        break;
576
577      case P_GSTRING:
578        strcpy((char *)parm_ptr,parmvalue);
579        break;
580
581      case P_ENUM:
582              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
583                      if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
584                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
585                              break;
586                      }
587              }
588              if (!parm_table[parmnum].enum_list[i].name) {
589                      if (atoi(parmvalue) > 0)
590                              *(int *)parm_ptr = atoi(parmvalue);
591              }
592              break;
593      case P_SEP:
594              break;
595      }
596
597    return(True);
598 }
599
600 /***************************************************************************
601 Process a parameter.
602 ***************************************************************************/
603 static BOOL do_parameter(char *parmname, char *parmvalue)
604 {
605    return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
606 }
607
608 /***************************************************************************
609 Process a new section (service). At this stage all sections are services.
610 Later we'll have special sections that permit server parameters to be set.
611 Returns True on success, False on failure.
612 ***************************************************************************/
613 static BOOL do_section(char *sectionname)
614 {
615    BOOL bRetval;
616    BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
617    bRetval = False;
618
619    /* if we were in a global section then do the local inits */
620    if (bInGlobalSection && !isglobal)
621      init_locals();
622
623    /* if we've just struck a global section, note the fact. */
624    bInGlobalSection = isglobal;   
625
626    /* check for multiple global sections */
627    if (bInGlobalSection)
628    {
629      return(True);
630    }
631
632    /* if we have a current service, tidy it up before moving on */
633    bRetval = True;
634
635    if (iServiceIndex >= 0)
636      bRetval = True;
637
638    /* if all is still well, move to the next record in the services array */
639    if (bRetval)
640      {
641        /* We put this here to avoid an odd message order if messages are */
642        /* issued by the post-processing of a previous section. */
643
644        if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
645          {
646            rprintf(FERROR,"Failed to add a new service\n");
647            return(False);
648          }
649      }
650
651    return (bRetval);
652 }
653
654
655 /***************************************************************************
656 Load the services array from the services file. Return True on success, 
657 False on failure.
658 ***************************************************************************/
659 BOOL lp_load(char *pszFname)
660 {
661   pstring n2;
662   BOOL bRetval;
663  
664   bRetval = False;
665
666   bInGlobalSection = True;
667   
668   init_globals();
669
670   pstrcpy(n2,pszFname);
671
672   /* We get sections first, so have to start 'behind' to make up */
673   iServiceIndex = -1;
674   bRetval = pm_process(n2, do_section, do_parameter);
675   
676   bLoaded = True;
677
678   return (bRetval);
679 }
680
681
682 /***************************************************************************
683 return the max number of services
684 ***************************************************************************/
685 int lp_numservices(void)
686 {
687   return(iNumServices);
688 }
689
690 /***************************************************************************
691 Return the number of the service with the given name, or -1 if it doesn't
692 exist. Note that this is a DIFFERENT ANIMAL from the internal function
693 getservicebyname()! This works ONLY if all services have been loaded, and
694 does not copy the found service.
695 ***************************************************************************/
696 int lp_number(char *name)
697 {
698    int iService;
699
700    for (iService = iNumServices - 1; iService >= 0; iService--)
701       if (strequal(lp_name(iService), name)) 
702          break;
703
704    return (iService);
705 }
706