load just the globals section of the config file when the daemon
[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         char *exclude;
127         char *exclude_from;
128 } service;
129
130
131 /* This is a default service used to prime a services structure */
132 static service sDefault = 
133 {
134         NULL,    /* name */
135         NULL,    /* path */
136         NULL,    /* comment */
137         True,    /* read only */
138         True,    /* list */
139         "nobody",/* uid */
140         "nobody",/* gid */
141         NULL,    /* hosts allow */
142         NULL,    /* hosts deny */
143         NULL,    /* auth users */
144         NULL,    /* secrets file */
145         NULL,    /* exclude */
146         NULL,    /* exclude from */
147 };
148
149
150
151 /* local variables */
152 static service **ServicePtrs = NULL;
153 static int iNumServices = 0;
154 static int iServiceIndex = 0;
155 static BOOL bInGlobalSection = True;
156
157 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
158
159 static struct enum_list enum_facilities[] = {
160 #ifdef LOG_AUTH
161         { LOG_AUTH, "auth" },
162 #endif
163 #ifdef LOG_AUTHPRIV
164         { LOG_AUTHPRIV, "authpriv" },
165 #endif
166 #ifdef LOG_CRON
167         { LOG_CRON, "cron" },
168 #endif
169 #ifdef LOG_DAEMON
170         { LOG_DAEMON, "daemon" },
171 #endif
172 #ifdef LOG_FTP
173         { LOG_FTP, "ftp" },
174 #endif
175 #ifdef LOG_KERN
176         { LOG_KERN, "kern" },
177 #endif
178 #ifdef LOG_LPR
179         { LOG_LPR, "lpr" },
180 #endif
181 #ifdef LOG_MAIL
182         { LOG_MAIL, "mail" },
183 #endif
184 #ifdef LOG_NEWS
185         { LOG_NEWS, "news" },
186 #endif
187 #ifdef LOG_AUTH
188         { LOG_AUTH, "security" },               
189 #endif
190 #ifdef LOG_SYSLOG
191         { LOG_SYSLOG, "syslog" },
192 #endif
193 #ifdef LOG_USER
194         { LOG_USER, "user" },
195 #endif
196 #ifdef LOG_UUCP
197         { LOG_UUCP, "uucp" },
198 #endif
199 #ifdef LOG_LOCAL0
200         { LOG_LOCAL0, "local0" },
201 #endif
202 #ifdef LOG_LOCAL1
203         { LOG_LOCAL1, "local1" },
204 #endif
205 #ifdef LOG_LOCAL2
206         { LOG_LOCAL2, "local2" },
207 #endif
208 #ifdef LOG_LOCAL3
209         { LOG_LOCAL3, "local3" },
210 #endif
211 #ifdef LOG_LOCAL4
212         { LOG_LOCAL4, "local4" },
213 #endif
214 #ifdef LOG_LOCAL5
215         { LOG_LOCAL5, "local5" },
216 #endif
217 #ifdef LOG_LOCAL6
218         { LOG_LOCAL6, "local6" },
219 #endif
220 #ifdef LOG_LOCAL7
221         { LOG_LOCAL7, "local7" },
222 #endif
223         { -1, NULL }};
224
225
226 /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
227 static struct parm_struct parm_table[] =
228 {
229   {"max connections",  P_INTEGER, P_GLOBAL, &Globals.max_connections,NULL, 0},
230   {"motd file",        P_STRING,  P_GLOBAL, &Globals.motd_file,    NULL,   0},
231   {"lock file",        P_STRING,  P_GLOBAL, &Globals.lock_file,    NULL,   0},
232   {"syslog facility",  P_ENUM,    P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
233
234   {"name",             P_STRING,  P_LOCAL,  &sDefault.name,        NULL,   0},
235   {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,     NULL,   0},
236   {"path",             P_STRING,  P_LOCAL,  &sDefault.path,        NULL,   0},
237   {"read only",        P_BOOL,    P_LOCAL,  &sDefault.read_only,   NULL,   0},
238   {"list",             P_BOOL,    P_LOCAL,  &sDefault.list,        NULL,   0},
239   {"uid",              P_STRING,  P_LOCAL,  &sDefault.uid,         NULL,   0},
240   {"gid",              P_STRING,  P_LOCAL,  &sDefault.gid,         NULL,   0},
241   {"hosts allow",      P_STRING,  P_LOCAL,  &sDefault.hosts_allow, NULL,   0},
242   {"hosts deny",       P_STRING,  P_LOCAL,  &sDefault.hosts_deny,  NULL,   0},
243   {"auth users",       P_STRING,  P_LOCAL,  &sDefault.auth_users,  NULL,   0},
244   {"secrets file",     P_STRING,  P_LOCAL,  &sDefault.secrets_file,NULL,   0},
245   {"exclude",          P_STRING,  P_LOCAL,  &sDefault.exclude,     NULL,   0},
246   {"exclude from",     P_STRING,  P_LOCAL,  &sDefault.exclude_from,NULL,   0},
247   {NULL,               P_BOOL,    P_NONE,   NULL,                  NULL,   0}
248 };
249
250
251 /***************************************************************************
252 Initialise the global parameter structure.
253 ***************************************************************************/
254 static void init_globals(void)
255 {
256         memset(&Globals, 0, sizeof(Globals));
257 #ifdef LOG_DAEMON
258         Globals.syslog_facility = LOG_DAEMON;
259 #endif
260         Globals.lock_file = "/var/run/rsyncd.lock";
261 }
262
263 /***************************************************************************
264 Initialise the sDefault parameter structure.
265 ***************************************************************************/
266 static void init_locals(void)
267 {
268 }
269
270
271 /*
272    In this section all the functions that are used to access the 
273    parameters from the rest of the program are defined 
274 */
275
276 #define FN_GLOBAL_STRING(fn_name,ptr) \
277  char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
278 #define FN_GLOBAL_BOOL(fn_name,ptr) \
279  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
280 #define FN_GLOBAL_CHAR(fn_name,ptr) \
281  char fn_name(void) {return(*(char *)(ptr));}
282 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
283  int fn_name(void) {return(*(int *)(ptr));}
284
285 #define FN_LOCAL_STRING(fn_name,val) \
286  char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
287 #define FN_LOCAL_BOOL(fn_name,val) \
288  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
289 #define FN_LOCAL_CHAR(fn_name,val) \
290  char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
291 #define FN_LOCAL_INTEGER(fn_name,val) \
292  int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
293
294
295 FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
296 FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
297 FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
298 FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
299 FN_LOCAL_STRING(lp_name, name)
300 FN_LOCAL_STRING(lp_comment, comment)
301 FN_LOCAL_STRING(lp_path, path)
302 FN_LOCAL_BOOL(lp_read_only, read_only)
303 FN_LOCAL_BOOL(lp_list, list)
304 FN_LOCAL_STRING(lp_uid, uid)
305 FN_LOCAL_STRING(lp_gid, gid)
306 FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
307 FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
308 FN_LOCAL_STRING(lp_auth_users, auth_users)
309 FN_LOCAL_STRING(lp_secrets_file, secrets_file)
310 FN_LOCAL_STRING(lp_exclude, exclude)
311 FN_LOCAL_STRING(lp_exclude_from, exclude_from)
312
313 /* local prototypes */
314 static int    strwicmp( char *psz1, char *psz2 );
315 static int    map_parameter( char *parmname);
316 static BOOL   set_boolean( BOOL *pb, char *parmvalue );
317 static int    getservicebyname(char *name, service *pserviceDest);
318 static void   copy_service( service *pserviceDest, 
319                             service *pserviceSource);
320 static BOOL   do_parameter(char *parmname, char *parmvalue);
321 static BOOL   do_section(char *sectionname);
322
323
324 /***************************************************************************
325 initialise a service to the defaults
326 ***************************************************************************/
327 static void init_service(service *pservice)
328 {
329         bzero((char *)pservice,sizeof(service));
330         copy_service(pservice,&sDefault);
331 }
332
333 static void string_set(char **s, char *v)
334 {
335         if (!v) {
336                 *s = NULL;
337                 return;
338         }
339         *s = strdup(v);
340         if (!*s) exit_cleanup(1);
341 }
342
343
344 /***************************************************************************
345 add a new service to the services array initialising it with the given 
346 service
347 ***************************************************************************/
348 static int add_a_service(service *pservice, char *name)
349 {
350   int i;
351   service tservice;
352   int num_to_alloc = iNumServices+1;
353
354   tservice = *pservice;
355
356   /* it might already exist */
357   if (name) 
358     {
359       i = getservicebyname(name,NULL);
360       if (i >= 0)
361         return(i);
362     }
363
364   i = iNumServices;
365
366   ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
367   if (ServicePtrs)
368           pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
369
370   if (!ServicePtrs || !pSERVICE(iNumServices))
371           return(-1);
372
373   iNumServices++;
374
375   init_service(pSERVICE(i));
376   copy_service(pSERVICE(i),&tservice);
377   if (name)
378     string_set(&iSERVICE(i).name,name);  
379
380   return(i);
381 }
382
383 /***************************************************************************
384 Do a case-insensitive, whitespace-ignoring string compare.
385 ***************************************************************************/
386 static int strwicmp(char *psz1, char *psz2)
387 {
388    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
389    /* appropriate value. */
390    if (psz1 == psz2)
391       return (0);
392    else
393       if (psz1 == NULL)
394          return (-1);
395       else
396           if (psz2 == NULL)
397               return (1);
398
399    /* sync the strings on first non-whitespace */
400    while (1)
401    {
402       while (isspace(*psz1))
403          psz1++;
404       while (isspace(*psz2))
405          psz2++;
406       if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
407          break;
408       psz1++;
409       psz2++;
410    }
411    return (*psz1 - *psz2);
412 }
413
414 /***************************************************************************
415 Map a parameter's string representation to something we can use. 
416 Returns False if the parameter string is not recognised, else TRUE.
417 ***************************************************************************/
418 static int map_parameter(char *parmname)
419 {
420    int iIndex;
421
422    if (*parmname == '-')
423      return(-1);
424
425    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
426       if (strwicmp(parm_table[iIndex].label, parmname) == 0)
427          return(iIndex);
428
429    rprintf(FERROR, "Unknown parameter encountered: \"%s\"\n", parmname);
430    return(-1);
431 }
432
433
434 /***************************************************************************
435 Set a boolean variable from the text value stored in the passed string.
436 Returns True in success, False if the passed string does not correctly 
437 represent a boolean.
438 ***************************************************************************/
439 static BOOL set_boolean(BOOL *pb, char *parmvalue)
440 {
441    BOOL bRetval;
442
443    bRetval = True;
444    if (strwicmp(parmvalue, "yes") == 0 ||
445        strwicmp(parmvalue, "true") == 0 ||
446        strwicmp(parmvalue, "1") == 0)
447       *pb = True;
448    else
449       if (strwicmp(parmvalue, "no") == 0 ||
450           strwicmp(parmvalue, "False") == 0 ||
451           strwicmp(parmvalue, "0") == 0)
452          *pb = False;
453       else
454       {
455          rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
456                parmvalue);
457          bRetval = False;
458       }
459    return (bRetval);
460 }
461
462 /***************************************************************************
463 Find a service by name. Otherwise works like get_service.
464 ***************************************************************************/
465 static int getservicebyname(char *name, service *pserviceDest)
466 {
467    int iService;
468
469    for (iService = iNumServices - 1; iService >= 0; iService--)
470       if (strwicmp(iSERVICE(iService).name, name) == 0) 
471       {
472          if (pserviceDest != NULL)
473            copy_service(pserviceDest, pSERVICE(iService));
474          break;
475       }
476
477    return (iService);
478 }
479
480
481
482 /***************************************************************************
483 Copy a service structure to another
484
485 ***************************************************************************/
486 static void copy_service(service *pserviceDest, 
487                          service *pserviceSource)
488 {
489   int i;
490
491   for (i=0;parm_table[i].label;i++)
492     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
493         void *def_ptr = parm_table[i].ptr;
494         void *src_ptr = 
495           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
496         void *dest_ptr = 
497           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
498
499         switch (parm_table[i].type)
500           {
501           case P_BOOL:
502           case P_BOOLREV:
503             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
504             break;
505
506           case P_INTEGER:
507           case P_ENUM:
508           case P_OCTAL:
509             *(int *)dest_ptr = *(int *)src_ptr;
510             break;
511
512           case P_CHAR:
513             *(char *)dest_ptr = *(char *)src_ptr;
514             break;
515
516           case P_STRING:
517             string_set(dest_ptr,*(char **)src_ptr);
518             break;
519
520           default:
521             break;
522           }
523       }
524 }
525
526
527 /***************************************************************************
528 Process a parameter for a particular service number. If snum < 0
529 then assume we are in the globals
530 ***************************************************************************/
531 static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
532 {
533    int parmnum, i;
534    void *parm_ptr=NULL; /* where we are going to store the result */
535    void *def_ptr=NULL;
536
537    parmnum = map_parameter(parmname);
538
539    if (parmnum < 0)
540      {
541        rprintf(FERROR, "Ignoring unknown parameter \"%s\"\n", parmname);
542        return(True);
543      }
544
545    def_ptr = parm_table[parmnum].ptr;
546
547    /* we might point at a service, the default service or a global */
548    if (snum < 0) {
549      parm_ptr = def_ptr;
550    } else {
551        if (parm_table[parmnum].class == P_GLOBAL) {
552            rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
553            return(True);
554          }
555        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
556    }
557
558    /* now switch on the type of variable it is */
559    switch (parm_table[parmnum].type)
560      {
561      case P_BOOL:
562        set_boolean(parm_ptr,parmvalue);
563        break;
564
565      case P_BOOLREV:
566        set_boolean(parm_ptr,parmvalue);
567        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
568        break;
569
570      case P_INTEGER:
571        *(int *)parm_ptr = atoi(parmvalue);
572        break;
573
574      case P_CHAR:
575        *(char *)parm_ptr = *parmvalue;
576        break;
577
578      case P_OCTAL:
579        sscanf(parmvalue,"%o",(int *)parm_ptr);
580        break;
581
582      case P_STRING:
583        string_set(parm_ptr,parmvalue);
584        break;
585
586      case P_GSTRING:
587        strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring)-1);
588        break;
589
590      case P_ENUM:
591              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
592                      if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
593                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
594                              break;
595                      }
596              }
597              if (!parm_table[parmnum].enum_list[i].name) {
598                      if (atoi(parmvalue) > 0)
599                              *(int *)parm_ptr = atoi(parmvalue);
600              }
601              break;
602      case P_SEP:
603              break;
604      }
605
606    return(True);
607 }
608
609 /***************************************************************************
610 Process a parameter.
611 ***************************************************************************/
612 static BOOL do_parameter(char *parmname, char *parmvalue)
613 {
614    return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
615 }
616
617 /***************************************************************************
618 Process a new section (service). At this stage all sections are services.
619 Later we'll have special sections that permit server parameters to be set.
620 Returns True on success, False on failure.
621 ***************************************************************************/
622 static BOOL do_section(char *sectionname)
623 {
624    BOOL bRetval;
625    BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
626    bRetval = False;
627
628    /* if we were in a global section then do the local inits */
629    if (bInGlobalSection && !isglobal)
630      init_locals();
631
632    /* if we've just struck a global section, note the fact. */
633    bInGlobalSection = isglobal;   
634
635    /* check for multiple global sections */
636    if (bInGlobalSection)
637    {
638      return(True);
639    }
640
641    /* if we have a current service, tidy it up before moving on */
642    bRetval = True;
643
644    if (iServiceIndex >= 0)
645      bRetval = True;
646
647    /* if all is still well, move to the next record in the services array */
648    if (bRetval)
649      {
650        /* We put this here to avoid an odd message order if messages are */
651        /* issued by the post-processing of a previous section. */
652
653        if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
654          {
655            rprintf(FERROR,"Failed to add a new service\n");
656            return(False);
657          }
658      }
659
660    return (bRetval);
661 }
662
663
664 /***************************************************************************
665 Load the services array from the services file. Return True on success, 
666 False on failure.
667 ***************************************************************************/
668 BOOL lp_load(char *pszFname, int globals_only)
669 {
670         pstring n2;
671         BOOL bRetval;
672  
673         bRetval = False;
674
675         bInGlobalSection = True;
676   
677         init_globals();
678
679         pstrcpy(n2,pszFname);
680
681         /* We get sections first, so have to start 'behind' to make up */
682         iServiceIndex = -1;
683         bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
684   
685         bLoaded = True;
686
687         return (bRetval);
688 }
689
690
691 /***************************************************************************
692 return the max number of services
693 ***************************************************************************/
694 int lp_numservices(void)
695 {
696   return(iNumServices);
697 }
698
699 /***************************************************************************
700 Return the number of the service with the given name, or -1 if it doesn't
701 exist. Note that this is a DIFFERENT ANIMAL from the internal function
702 getservicebyname()! This works ONLY if all services have been loaded, and
703 does not copy the found service.
704 ***************************************************************************/
705 int lp_number(char *name)
706 {
707    int iService;
708
709    for (iService = iNumServices - 1; iService >= 0; iService--)
710       if (strequal(lp_name(iService), name)) 
711          break;
712
713    return (iService);
714 }
715