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