Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

loadparm.c

Go to the documentation of this file.
00001 /* This is based on loadparm.c from Samba, written by Andrew Tridgell
00002    and Karl Auer */
00003 
00004 /* some fixes
00005  *
00006  * Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
00007  */
00008 
00009 /* 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 /*
00026  *  Load parameters.
00027  *
00028  *  This module provides suitable callback functions for the params
00029  *  module. It builds the internal table of service details which is
00030  *  then used by the rest of the server.
00031  *
00032  * To add a parameter:
00033  *
00034  * 1) add it to the global or service structure definition
00035  * 2) add it to the parm_table
00036  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
00037  * 4) If it's a global then initialise it in init_globals. If a local
00038  *    (ie. service) parameter then initialise it in the sDefault structure
00039  *  
00040  *
00041  * Notes:
00042  *   The configuration file is processed sequentially for speed. It is NOT
00043  *   accessed randomly as happens in 'real' Windows. For this reason, there
00044  *   is a fair bit of sequence-dependent code here - ie., code which assumes
00045  *   that certain things happen before others. In particular, the code which
00046  *   happens at the boundary between sections is delicately poised, so be
00047  *   careful!
00048  *
00049  */
00050 
00051 /* TODO: Parameter to set debug level on server. */
00052 
00053 #include "rsync.h"
00054 #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
00055 #define strequal(a,b) (strcasecmp(a,b)==0)
00056 #define BOOLSTR(b) ((b) ? "Yes" : "No")
00057 typedef char pstring[1024];
00058 #define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
00059 
00060 /* the following are used by loadparm for option lists */
00061 typedef enum
00062 {
00063         P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
00064         P_STRING,P_GSTRING,P_ENUM,P_SEP
00065 } parm_type;
00066 
00067 typedef enum
00068 {
00069         P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
00070 } parm_class;
00071 
00072 struct enum_list {
00073         int value;
00074         char *name;
00075 };
00076 
00077 struct parm_struct
00078 {
00079         char *label;
00080         parm_type type;
00081         parm_class class;
00082         void *ptr;
00083         struct enum_list *enum_list;
00084         unsigned flags;
00085 };
00086 
00087 #ifndef GLOBAL_NAME
00088 #define GLOBAL_NAME "global"
00089 #endif
00090 
00091 /* some helpful bits */
00092 #define pSERVICE(i) ServicePtrs[i]
00093 #define iSERVICE(i) (*pSERVICE(i))
00094 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
00095 
00096 /* 
00097  * This structure describes global (ie., server-wide) parameters.
00098  */
00099 typedef struct
00100 {
00101         char *motd_file;
00102         char *log_file;
00103         char *pid_file;
00104         int syslog_facility;
00105         char *socket_options;
00106 } global;
00107 
00108 static global Globals;
00109 
00110 
00111 
00112 /* 
00113  * This structure describes a single service. 
00114  */
00115 typedef struct
00116 {
00117         char *name;
00118         char *path;
00119         char *comment;
00120         char *lock_file;
00121         BOOL read_only;
00122         BOOL list;
00123         BOOL use_chroot;
00124         BOOL transfer_logging;
00125         BOOL ignore_errors;
00126         char *uid;
00127         char *gid;
00128         char *hosts_allow;
00129         char *hosts_deny;
00130         char *auth_users;
00131         char *secrets_file;
00132         BOOL strict_modes;
00133         char *exclude;
00134         char *exclude_from;
00135         char *include;
00136         char *include_from;
00137         char *log_format;
00138         char *refuse_options;
00139         char *dont_compress;
00140         int timeout;
00141         int max_connections;
00142         BOOL ignore_nonreadable;
00143 } service;
00144 
00145 
00146 /* This is a default service used to prime a services structure */
00147 static service sDefault = 
00148 {
00149         NULL,    /* name */
00150         NULL,    /* path */
00151         NULL,    /* comment */
00152         DEFAULT_LOCK_FILE,    /* lock file */
00153         True,    /* read only */
00154         True,    /* list */
00155         True,    /* use chroot */
00156         False,   /* transfer logging */
00157         False,   /* ignore errors */
00158         "nobody",/* uid */
00159         
00160         /* TODO: This causes problems on Debian, where it is called
00161          * "nogroup".  Debian patch this in their version of the
00162          * package, but it would be nice to be consistent.  Possibly
00163          * other systems are different again.
00164          *
00165          * What is the best behaviour?  Perhaps always using (gid_t)
00166          * -2? */
00167         "nobody",/* gid */
00168         
00169         NULL,    /* hosts allow */
00170         NULL,    /* hosts deny */
00171         NULL,    /* auth users */
00172         NULL,    /* secrets file */
00173         True,   /* strict modes */
00174         NULL,    /* exclude */
00175         NULL,    /* exclude from */
00176         NULL,    /* include */
00177         NULL,    /* include from */
00178         "%o %h [%a] %m (%u) %f %l",    /* log format */
00179         NULL,    /* refuse options */
00180         "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",    /* dont compress */
00181         0,        /* timeout */
00182         0,        /* max connections */
00183         False     /* ignore nonreadable */
00184 };
00185 
00186 
00187 
00188 /* local variables */
00189 static service **ServicePtrs = NULL;
00190 static int iNumServices = 0;
00191 static int iServiceIndex = 0;
00192 static BOOL bInGlobalSection = True;
00193 
00194 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
00195 
00196 static struct enum_list enum_facilities[] = {
00197 #ifdef LOG_AUTH
00198         { LOG_AUTH, "auth" },
00199 #endif
00200 #ifdef LOG_AUTHPRIV
00201         { LOG_AUTHPRIV, "authpriv" },
00202 #endif
00203 #ifdef LOG_CRON
00204         { LOG_CRON, "cron" },
00205 #endif
00206 #ifdef LOG_DAEMON
00207         { LOG_DAEMON, "daemon" },
00208 #endif
00209 #ifdef LOG_FTP
00210         { LOG_FTP, "ftp" },
00211 #endif
00212 #ifdef LOG_KERN
00213         { LOG_KERN, "kern" },
00214 #endif
00215 #ifdef LOG_LPR
00216         { LOG_LPR, "lpr" },
00217 #endif
00218 #ifdef LOG_MAIL
00219         { LOG_MAIL, "mail" },
00220 #endif
00221 #ifdef LOG_NEWS
00222         { LOG_NEWS, "news" },
00223 #endif
00224 #ifdef LOG_AUTH
00225         { LOG_AUTH, "security" },               
00226 #endif
00227 #ifdef LOG_SYSLOG
00228         { LOG_SYSLOG, "syslog" },
00229 #endif
00230 #ifdef LOG_USER
00231         { LOG_USER, "user" },
00232 #endif
00233 #ifdef LOG_UUCP
00234         { LOG_UUCP, "uucp" },
00235 #endif
00236 #ifdef LOG_LOCAL0
00237         { LOG_LOCAL0, "local0" },
00238 #endif
00239 #ifdef LOG_LOCAL1
00240         { LOG_LOCAL1, "local1" },
00241 #endif
00242 #ifdef LOG_LOCAL2
00243         { LOG_LOCAL2, "local2" },
00244 #endif
00245 #ifdef LOG_LOCAL3
00246         { LOG_LOCAL3, "local3" },
00247 #endif
00248 #ifdef LOG_LOCAL4
00249         { LOG_LOCAL4, "local4" },
00250 #endif
00251 #ifdef LOG_LOCAL5
00252         { LOG_LOCAL5, "local5" },
00253 #endif
00254 #ifdef LOG_LOCAL6
00255         { LOG_LOCAL6, "local6" },
00256 #endif
00257 #ifdef LOG_LOCAL7
00258         { LOG_LOCAL7, "local7" },
00259 #endif
00260         { -1, NULL }};
00261 
00262 
00263 /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
00264 static struct parm_struct parm_table[] =
00265 {
00266   {"motd file",        P_STRING,  P_GLOBAL, &Globals.motd_file,    NULL,   0},
00267   {"syslog facility",  P_ENUM,    P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
00268   {"socket options",   P_STRING,  P_GLOBAL, &Globals.socket_options,NULL,  0},
00269   {"log file",         P_STRING,  P_GLOBAL, &Globals.log_file,      NULL,  0},
00270   {"pid file",         P_STRING,  P_GLOBAL, &Globals.pid_file,      NULL,  0},
00271 
00272   {"timeout",          P_INTEGER, P_LOCAL,  &sDefault.timeout,     NULL,  0},
00273   {"max connections",  P_INTEGER, P_LOCAL,  &sDefault.max_connections,NULL, 0},
00274   {"name",             P_STRING,  P_LOCAL,  &sDefault.name,        NULL,   0},
00275   {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,     NULL,   0},
00276   {"lock file",        P_STRING,  P_LOCAL,  &sDefault.lock_file,   NULL,   0},
00277   {"path",             P_STRING,  P_LOCAL,  &sDefault.path,        NULL,   0},
00278   {"read only",        P_BOOL,    P_LOCAL,  &sDefault.read_only,   NULL,   0},
00279   {"list",             P_BOOL,    P_LOCAL,  &sDefault.list,        NULL,   0},
00280   {"use chroot",       P_BOOL,    P_LOCAL,  &sDefault.use_chroot,  NULL,   0},
00281   {"ignore nonreadable",P_BOOL,   P_LOCAL,  &sDefault.ignore_nonreadable,  NULL,   0},
00282   {"uid",              P_STRING,  P_LOCAL,  &sDefault.uid,         NULL,   0},
00283   {"gid",              P_STRING,  P_LOCAL,  &sDefault.gid,         NULL,   0},
00284   {"hosts allow",      P_STRING,  P_LOCAL,  &sDefault.hosts_allow, NULL,   0},
00285   {"hosts deny",       P_STRING,  P_LOCAL,  &sDefault.hosts_deny,  NULL,   0},
00286   {"auth users",       P_STRING,  P_LOCAL,  &sDefault.auth_users,  NULL,   0},
00287   {"secrets file",     P_STRING,  P_LOCAL,  &sDefault.secrets_file,NULL,   0},
00288   {"strict modes",     P_BOOL,    P_LOCAL,  &sDefault.strict_modes,NULL,   0},
00289   {"exclude",          P_STRING,  P_LOCAL,  &sDefault.exclude,     NULL,   0},
00290   {"exclude from",     P_STRING,  P_LOCAL,  &sDefault.exclude_from,NULL,   0},
00291   {"include",          P_STRING,  P_LOCAL,  &sDefault.include,     NULL,   0},
00292   {"include from",     P_STRING,  P_LOCAL,  &sDefault.include_from,NULL,   0},
00293   {"transfer logging", P_BOOL,    P_LOCAL,  &sDefault.transfer_logging,NULL,0},
00294   {"ignore errors",    P_BOOL,    P_LOCAL,  &sDefault.ignore_errors,NULL,0},
00295   {"log format",       P_STRING,  P_LOCAL,  &sDefault.log_format,  NULL,   0},
00296   {"refuse options",   P_STRING,  P_LOCAL,  &sDefault.refuse_options,NULL, 0},
00297   {"dont compress",    P_STRING,  P_LOCAL,  &sDefault.dont_compress,NULL,  0},
00298   {NULL,               P_BOOL,    P_NONE,   NULL,                  NULL,   0}
00299 };
00300 
00301 
00302 /***************************************************************************
00303 Initialise the global parameter structure.
00304 ***************************************************************************/
00305 static void init_globals(void)
00306 {
00307         memset(&Globals, 0, sizeof(Globals));
00308 #ifdef LOG_DAEMON
00309         Globals.syslog_facility = LOG_DAEMON;
00310 #endif
00311 }
00312 
00313 /***************************************************************************
00314 Initialise the sDefault parameter structure.
00315 ***************************************************************************/
00316 static void init_locals(void)
00317 {
00318 }
00319 
00320 
00321 /*
00322    In this section all the functions that are used to access the 
00323    parameters from the rest of the program are defined 
00324 */
00325 
00326 #define FN_GLOBAL_STRING(fn_name,ptr) \
00327  char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
00328 #define FN_GLOBAL_BOOL(fn_name,ptr) \
00329  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
00330 #define FN_GLOBAL_CHAR(fn_name,ptr) \
00331  char fn_name(void) {return(*(char *)(ptr));}
00332 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
00333  int fn_name(void) {return(*(int *)(ptr));}
00334 
00335 #define FN_LOCAL_STRING(fn_name,val) \
00336  char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
00337 #define FN_LOCAL_BOOL(fn_name,val) \
00338  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
00339 #define FN_LOCAL_CHAR(fn_name,val) \
00340  char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
00341 #define FN_LOCAL_INTEGER(fn_name,val) \
00342  int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
00343 
00344 
00345 FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
00346 FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
00347 FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
00348 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
00349 FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
00350 
00351 FN_LOCAL_STRING(lp_name, name)
00352 FN_LOCAL_STRING(lp_comment, comment)
00353 FN_LOCAL_STRING(lp_path, path)
00354 FN_LOCAL_STRING(lp_lock_file, lock_file)
00355 FN_LOCAL_BOOL(lp_read_only, read_only)
00356 FN_LOCAL_BOOL(lp_list, list)
00357 FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
00358 FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
00359 FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
00360 FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
00361 FN_LOCAL_STRING(lp_uid, uid)
00362 FN_LOCAL_STRING(lp_gid, gid)
00363 FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
00364 FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
00365 FN_LOCAL_STRING(lp_auth_users, auth_users)
00366 FN_LOCAL_STRING(lp_secrets_file, secrets_file)
00367 FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
00368 FN_LOCAL_STRING(lp_exclude, exclude)
00369 FN_LOCAL_STRING(lp_exclude_from, exclude_from)
00370 FN_LOCAL_STRING(lp_include, include)
00371 FN_LOCAL_STRING(lp_include_from, include_from)
00372 FN_LOCAL_STRING(lp_log_format, log_format)
00373 FN_LOCAL_STRING(lp_refuse_options, refuse_options)
00374 FN_LOCAL_STRING(lp_dont_compress, dont_compress)
00375 FN_LOCAL_INTEGER(lp_timeout, timeout)
00376 FN_LOCAL_INTEGER(lp_max_connections, max_connections)
00377 
00378 /* local prototypes */
00379 static int    strwicmp( char *psz1, char *psz2 );
00380 static int    map_parameter( char *parmname);
00381 static BOOL   set_boolean( BOOL *pb, char *parmvalue );
00382 static int    getservicebyname(char *name, service *pserviceDest);
00383 static void   copy_service( service *pserviceDest, 
00384                             service *pserviceSource);
00385 static BOOL   do_parameter(char *parmname, char *parmvalue);
00386 static BOOL   do_section(char *sectionname);
00387 
00388 
00389 /***************************************************************************
00390 initialise a service to the defaults
00391 ***************************************************************************/
00392 static void init_service(service *pservice)
00393 {
00394         memset((char *)pservice,0,sizeof(service));
00395         copy_service(pservice,&sDefault);
00396 }
00397 
00398 
00399 /**
00400  * Assign a copy of @p v to @p *s.  Handles NULL strings.  @p *v must
00401  * be initialized when this is called, either to NULL or a malloc'd
00402  * string.
00403  *
00404  * @fixme There is a small leak here in that sometimes the existing
00405  * value will be dynamically allocated, and the old copy is lost.
00406  * However, we can't always deallocate the old value, because in the
00407  * case of sDefault, it points to a static string.  It would be nice
00408  * to have either all-strdup'd values, or to never need to free
00409  * memory.
00410  **/
00411 static void string_set(char **s, const char *v)
00412 {
00413         if (!v) {
00414                 *s = NULL;
00415                 return;
00416         }
00417         *s = strdup(v);
00418         if (!*s)
00419                 exit_cleanup(RERR_MALLOC);
00420 }
00421 
00422 
00423 /***************************************************************************
00424 add a new service to the services array initialising it with the given 
00425 service
00426 ***************************************************************************/
00427 static int add_a_service(service *pservice, char *name)
00428 {
00429   int i;
00430   service tservice;
00431   int num_to_alloc = iNumServices+1;
00432 
00433   tservice = *pservice;
00434 
00435   /* it might already exist */
00436   if (name) 
00437     {
00438       i = getservicebyname(name,NULL);
00439       if (i >= 0)
00440         return(i);
00441     }
00442 
00443   i = iNumServices;
00444 
00445   ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
00446 
00447   if (ServicePtrs)
00448           pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
00449 
00450   if (!ServicePtrs || !pSERVICE(iNumServices))
00451           return(-1);
00452 
00453   iNumServices++;
00454 
00455   init_service(pSERVICE(i));
00456   copy_service(pSERVICE(i),&tservice);
00457   if (name)
00458     string_set(&iSERVICE(i).name,name);  
00459 
00460   return(i);
00461 }
00462 
00463 /***************************************************************************
00464 Do a case-insensitive, whitespace-ignoring string compare.
00465 ***************************************************************************/
00466 static int strwicmp(char *psz1, char *psz2)
00467 {
00468    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
00469    /* appropriate value. */
00470    if (psz1 == psz2)
00471       return (0);
00472    else
00473       if (psz1 == NULL)
00474          return (-1);
00475       else
00476           if (psz2 == NULL)
00477               return (1);
00478 
00479    /* sync the strings on first non-whitespace */
00480    while (1)
00481    {
00482       while (isspace(* (unsigned char *) psz1))
00483          psz1++;
00484       while (isspace(* (unsigned char *) psz2))
00485          psz2++;
00486       if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
00487           || *psz1 == '\0' || *psz2 == '\0')
00488          break;
00489       psz1++;
00490       psz2++;
00491    }
00492    return (*psz1 - *psz2);
00493 }
00494 
00495 /***************************************************************************
00496 Map a parameter's string representation to something we can use. 
00497 Returns False if the parameter string is not recognised, else TRUE.
00498 ***************************************************************************/
00499 static int map_parameter(char *parmname)
00500 {
00501    int iIndex;
00502 
00503    if (*parmname == '-')
00504      return(-1);
00505 
00506    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
00507       if (strwicmp(parm_table[iIndex].label, parmname) == 0)
00508          return(iIndex);
00509 
00510    rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
00511    return(-1);
00512 }
00513 
00514 
00515 /***************************************************************************
00516 Set a boolean variable from the text value stored in the passed string.
00517 Returns True in success, False if the passed string does not correctly 
00518 represent a boolean.
00519 ***************************************************************************/
00520 static BOOL set_boolean(BOOL *pb, char *parmvalue)
00521 {
00522    BOOL bRetval;
00523 
00524    bRetval = True;
00525    if (strwicmp(parmvalue, "yes") == 0 ||
00526        strwicmp(parmvalue, "true") == 0 ||
00527        strwicmp(parmvalue, "1") == 0)
00528       *pb = True;
00529    else
00530       if (strwicmp(parmvalue, "no") == 0 ||
00531           strwicmp(parmvalue, "False") == 0 ||
00532           strwicmp(parmvalue, "0") == 0)
00533          *pb = False;
00534       else
00535       {
00536          rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
00537                parmvalue);
00538          bRetval = False;
00539       }
00540    return (bRetval);
00541 }
00542 
00543 /***************************************************************************
00544 Find a service by name. Otherwise works like get_service.
00545 ***************************************************************************/
00546 static int getservicebyname(char *name, service *pserviceDest)
00547 {
00548    int iService;
00549 
00550    for (iService = iNumServices - 1; iService >= 0; iService--)
00551       if (strwicmp(iSERVICE(iService).name, name) == 0) 
00552       {
00553          if (pserviceDest != NULL)
00554            copy_service(pserviceDest, pSERVICE(iService));
00555          break;
00556       }
00557 
00558    return (iService);
00559 }
00560 
00561 
00562 
00563 /***************************************************************************
00564 Copy a service structure to another
00565 
00566 ***************************************************************************/
00567 static void copy_service(service *pserviceDest, 
00568                          service *pserviceSource)
00569 {
00570   int i;
00571 
00572   for (i=0;parm_table[i].label;i++)
00573     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
00574         void *def_ptr = parm_table[i].ptr;
00575         void *src_ptr = 
00576           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
00577         void *dest_ptr = 
00578           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
00579 
00580         switch (parm_table[i].type)
00581           {
00582           case P_BOOL:
00583           case P_BOOLREV:
00584             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
00585             break;
00586 
00587           case P_INTEGER:
00588           case P_ENUM:
00589           case P_OCTAL:
00590             *(int *)dest_ptr = *(int *)src_ptr;
00591             break;
00592 
00593           case P_CHAR:
00594             *(char *)dest_ptr = *(char *)src_ptr;
00595             break;
00596 
00597           case P_STRING:
00598             string_set(dest_ptr,*(char **)src_ptr);
00599             break;
00600 
00601           default:
00602             break;
00603           }
00604       }
00605 }
00606 
00607 
00608 /***************************************************************************
00609 Process a parameter for a particular service number. If snum < 0
00610 then assume we are in the globals
00611 ***************************************************************************/
00612 static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
00613 {
00614    int parmnum, i;
00615    void *parm_ptr=NULL; /* where we are going to store the result */
00616    void *def_ptr=NULL;
00617 
00618    parmnum = map_parameter(parmname);
00619 
00620    if (parmnum < 0)
00621      {
00622        rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
00623        return(True);
00624      }
00625 
00626    def_ptr = parm_table[parmnum].ptr;
00627 
00628    /* we might point at a service, the default service or a global */
00629    if (snum < 0) {
00630      parm_ptr = def_ptr;
00631    } else {
00632        if (parm_table[parmnum].class == P_GLOBAL) {
00633            rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
00634            return(True);
00635          }
00636        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
00637    }
00638 
00639    /* now switch on the type of variable it is */
00640    switch (parm_table[parmnum].type)
00641      {
00642      case P_BOOL:
00643        set_boolean(parm_ptr,parmvalue);
00644        break;
00645 
00646      case P_BOOLREV:
00647        set_boolean(parm_ptr,parmvalue);
00648        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
00649        break;
00650 
00651      case P_INTEGER:
00652        *(int *)parm_ptr = atoi(parmvalue);
00653        break;
00654 
00655      case P_CHAR:
00656        *(char *)parm_ptr = *parmvalue;
00657        break;
00658 
00659      case P_OCTAL:
00660        sscanf(parmvalue,"%o",(int *)parm_ptr);
00661        break;
00662 
00663      case P_STRING:
00664        string_set(parm_ptr,parmvalue);
00665        break;
00666 
00667      case P_GSTRING:
00668        strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring));
00669        break;
00670 
00671      case P_ENUM:
00672              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
00673                      if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
00674                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
00675                              break;
00676                      }
00677              }
00678              if (!parm_table[parmnum].enum_list[i].name) {
00679                      if (atoi(parmvalue) > 0)
00680                              *(int *)parm_ptr = atoi(parmvalue);
00681              }
00682              break;
00683      case P_SEP:
00684              break;
00685      }
00686 
00687    return(True);
00688 }
00689 
00690 /***************************************************************************
00691 Process a parameter.
00692 ***************************************************************************/
00693 static BOOL do_parameter(char *parmname, char *parmvalue)
00694 {
00695    return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
00696 }
00697 
00698 /***************************************************************************
00699 Process a new section (service). At this stage all sections are services.
00700 Later we'll have special sections that permit server parameters to be set.
00701 Returns True on success, False on failure.
00702 ***************************************************************************/
00703 static BOOL do_section(char *sectionname)
00704 {
00705    BOOL bRetval;
00706    BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
00707    bRetval = False;
00708 
00709    /* if we were in a global section then do the local inits */
00710    if (bInGlobalSection && !isglobal)
00711      init_locals();
00712 
00713    /* if we've just struck a global section, note the fact. */
00714    bInGlobalSection = isglobal;   
00715 
00716    /* check for multiple global sections */
00717    if (bInGlobalSection)
00718    {
00719      return(True);
00720    }
00721 
00722    /* if we have a current service, tidy it up before moving on */
00723    bRetval = True;
00724 
00725    if (iServiceIndex >= 0)
00726      bRetval = True;
00727 
00728    /* if all is still well, move to the next record in the services array */
00729    if (bRetval)
00730      {
00731        /* We put this here to avoid an odd message order if messages are */
00732        /* issued by the post-processing of a previous section. */
00733 
00734        if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
00735          {
00736            rprintf(FERROR,"Failed to add a new service\n");
00737            return(False);
00738          }
00739      }
00740 
00741    return (bRetval);
00742 }
00743 
00744 
00745 /***************************************************************************
00746 Load the services array from the services file. Return True on success, 
00747 False on failure.
00748 ***************************************************************************/
00749 BOOL lp_load(char *pszFname, int globals_only)
00750 {
00751         pstring n2;
00752         BOOL bRetval;
00753  
00754         bRetval = False;
00755 
00756         bInGlobalSection = True;
00757   
00758         init_globals();
00759 
00760         pstrcpy(n2,pszFname);
00761 
00762         /* We get sections first, so have to start 'behind' to make up */
00763         iServiceIndex = -1;
00764         bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
00765   
00766         return (bRetval);
00767 }
00768 
00769 
00770 /***************************************************************************
00771 return the max number of services
00772 ***************************************************************************/
00773 int lp_numservices(void)
00774 {
00775   return(iNumServices);
00776 }
00777 
00778 /***************************************************************************
00779 Return the number of the service with the given name, or -1 if it doesn't
00780 exist. Note that this is a DIFFERENT ANIMAL from the internal function
00781 getservicebyname()! This works ONLY if all services have been loaded, and
00782 does not copy the found service.
00783 ***************************************************************************/
00784 int lp_number(char *name)
00785 {
00786    int iService;
00787 
00788    for (iService = iNumServices - 1; iService >= 0; iService--)
00789       if (strequal(lp_name(iService), name)) 
00790          break;
00791 
00792    return (iService);
00793 }
00794 

Generated on Tue Apr 16 12:37:36 2002 for rsync by doxygen1.2.15