Annotation of embedaddon/rsync/loadparm.c, revision 1.1.1.1
1.1 misho 1: /*
2: * This program is free software; you can redistribute it and/or modify
3: * it under the terms of the GNU General Public License as published by
4: * the Free Software Foundation; either version 3 of the License, or
5: * (at your option) any later version.
6: *
7: * This program is distributed in the hope that it will be useful,
8: * but WITHOUT ANY WARRANTY; without even the implied warranty of
9: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10: * GNU General Public License for more details.
11: *
12: * You should have received a copy of the GNU General Public License along
13: * with this program; if not, visit the http://fsf.org website.
14: */
15:
16: /* This is based on loadparm.c from Samba, written by Andrew Tridgell
17: * and Karl Auer. Some of the changes are:
18: *
19: * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
20: * Copyright (C) 2003-2009 Wayne Davison <wayned@samba.org>
21: */
22:
23: /* Load parameters.
24: *
25: * This module provides suitable callback functions for the params
26: * module. It builds the internal table of service details which is
27: * then used by the rest of the server.
28: *
29: * To add a parameter:
30: *
31: * 1) add it to the global or service structure definition
32: * 2) add it to the parm_table
33: * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
34: * 4) If it's a global then initialise it in init_globals. If a local
35: * (ie. service) parameter then initialise it in the sDefault structure
36: *
37: *
38: * Notes:
39: * The configuration file is processed sequentially for speed. It is NOT
40: * accessed randomly as happens in 'real' Windows. For this reason, there
41: * is a fair bit of sequence-dependent code here - ie., code which assumes
42: * that certain things happen before others. In particular, the code which
43: * happens at the boundary between sections is delicately poised, so be
44: * careful!
45: *
46: */
47:
48: /* TODO: Parameter to set debug level on server. */
49:
50: #include "rsync.h"
51: #include "ifuncs.h"
52: #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
53: #define strequal(a,b) (strcasecmp(a,b)==0)
54: #define BOOLSTR(b) ((b) ? "Yes" : "No")
55: typedef char pstring[1024];
56: #define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
57:
58: #ifndef LOG_DAEMON
59: #define LOG_DAEMON 0
60: #endif
61:
62: #define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
63: " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg"
64:
65: /* the following are used by loadparm for option lists */
66: typedef enum
67: {
68: P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
69: P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
70: } parm_type;
71:
72: typedef enum
73: {
74: P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
75: } parm_class;
76:
77: struct enum_list {
78: int value;
79: char *name;
80: };
81:
82: struct parm_struct
83: {
84: char *label;
85: parm_type type;
86: parm_class class;
87: void *ptr;
88: struct enum_list *enum_list;
89: unsigned flags;
90: };
91:
92: #ifndef GLOBAL_NAME
93: #define GLOBAL_NAME "global"
94: #endif
95:
96: /* some helpful bits */
97: #define pSERVICE(i) ServicePtrs[i]
98: #define iSERVICE(i) (*pSERVICE(i))
99: #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
100:
101: /*
102: * This structure describes global (ie., server-wide) parameters.
103: */
104: typedef struct
105: {
106: char *bind_address;
107: char *motd_file;
108: char *pid_file;
109: char *socket_options;
110:
111: int rsync_port;
112: } global;
113:
114: static global Globals;
115:
116:
117: /*
118: * This structure describes a single service. Their order must match the
119: * initializers below, which you can accomplish by keeping each sub-section
120: * sorted. (e.g. in vim, just visually select each subsection and use !sort.)
121: */
122: typedef struct
123: {
124: char *auth_users;
125: char *charset;
126: char *comment;
127: char *dont_compress;
128: char *exclude;
129: char *exclude_from;
130: char *filter;
131: char *gid;
132: char *hosts_allow;
133: char *hosts_deny;
134: char *include;
135: char *include_from;
136: char *incoming_chmod;
137: char *lock_file;
138: char *log_file;
139: char *log_format;
140: char *name;
141: char *outgoing_chmod;
142: char *path;
143: char *postxfer_exec;
144: char *prexfer_exec;
145: char *refuse_options;
146: char *secrets_file;
147: char *temp_dir;
148: char *uid;
149:
150: int max_connections;
151: int max_verbosity;
152: int syslog_facility;
153: int timeout;
154:
155: BOOL fake_super;
156: BOOL ignore_errors;
157: BOOL ignore_nonreadable;
158: BOOL list;
159: BOOL munge_symlinks;
160: BOOL numeric_ids;
161: BOOL read_only;
162: BOOL strict_modes;
163: BOOL transfer_logging;
164: BOOL use_chroot;
165: BOOL write_only;
166: } service;
167:
168:
169: /* This is a default service used to prime a services structure. In order
170: * to make these easy to keep sorted in the same way as the variables
171: * above, use the variable name in the leading comment, including a
172: * trailing ';' (to avoid a sorting problem with trailing digits). */
173: static service sDefault =
174: {
175: /* auth_users; */ NULL,
176: /* charset; */ NULL,
177: /* comment; */ NULL,
178: /* dont_compress; */ DEFAULT_DONT_COMPRESS,
179: /* exclude; */ NULL,
180: /* exclude_from; */ NULL,
181: /* filter; */ NULL,
182: /* gid; */ NOBODY_GROUP,
183: /* hosts_allow; */ NULL,
184: /* hosts_deny; */ NULL,
185: /* include; */ NULL,
186: /* include_from; */ NULL,
187: /* incoming_chmod; */ NULL,
188: /* lock_file; */ DEFAULT_LOCK_FILE,
189: /* log_file; */ NULL,
190: /* log_format; */ "%o %h [%a] %m (%u) %f %l",
191: /* name; */ NULL,
192: /* outgoing_chmod; */ NULL,
193: /* path; */ NULL,
194: /* postxfer_exec; */ NULL,
195: /* prexfer_exec; */ NULL,
196: /* refuse_options; */ NULL,
197: /* secrets_file; */ NULL,
198: /* temp_dir; */ NULL,
199: /* uid; */ NOBODY_USER,
200:
201: /* max_connections; */ 0,
202: /* max_verbosity; */ 1,
203: /* syslog_facility; */ LOG_DAEMON,
204: /* timeout; */ 0,
205:
206: /* fake_super; */ False,
207: /* ignore_errors; */ False,
208: /* ignore_nonreadable; */ False,
209: /* list; */ True,
210: /* munge_symlinks; */ (BOOL)-1,
211: /* numeric_ids; */ (BOOL)-1,
212: /* read_only; */ True,
213: /* strict_modes; */ True,
214: /* transfer_logging; */ False,
215: /* use_chroot; */ True,
216: /* write_only; */ False,
217: };
218:
219:
220:
221: /* local variables */
222: static service **ServicePtrs = NULL;
223: static int iNumServices = 0;
224: static int iServiceIndex = 0;
225: static BOOL bInGlobalSection = True;
226:
227: #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
228:
229: static struct enum_list enum_facilities[] = {
230: #ifdef LOG_AUTH
231: { LOG_AUTH, "auth" },
232: #endif
233: #ifdef LOG_AUTHPRIV
234: { LOG_AUTHPRIV, "authpriv" },
235: #endif
236: #ifdef LOG_CRON
237: { LOG_CRON, "cron" },
238: #endif
239: #ifdef LOG_DAEMON
240: { LOG_DAEMON, "daemon" },
241: #endif
242: #ifdef LOG_FTP
243: { LOG_FTP, "ftp" },
244: #endif
245: #ifdef LOG_KERN
246: { LOG_KERN, "kern" },
247: #endif
248: #ifdef LOG_LPR
249: { LOG_LPR, "lpr" },
250: #endif
251: #ifdef LOG_MAIL
252: { LOG_MAIL, "mail" },
253: #endif
254: #ifdef LOG_NEWS
255: { LOG_NEWS, "news" },
256: #endif
257: #ifdef LOG_AUTH
258: { LOG_AUTH, "security" },
259: #endif
260: #ifdef LOG_SYSLOG
261: { LOG_SYSLOG, "syslog" },
262: #endif
263: #ifdef LOG_USER
264: { LOG_USER, "user" },
265: #endif
266: #ifdef LOG_UUCP
267: { LOG_UUCP, "uucp" },
268: #endif
269: #ifdef LOG_LOCAL0
270: { LOG_LOCAL0, "local0" },
271: #endif
272: #ifdef LOG_LOCAL1
273: { LOG_LOCAL1, "local1" },
274: #endif
275: #ifdef LOG_LOCAL2
276: { LOG_LOCAL2, "local2" },
277: #endif
278: #ifdef LOG_LOCAL3
279: { LOG_LOCAL3, "local3" },
280: #endif
281: #ifdef LOG_LOCAL4
282: { LOG_LOCAL4, "local4" },
283: #endif
284: #ifdef LOG_LOCAL5
285: { LOG_LOCAL5, "local5" },
286: #endif
287: #ifdef LOG_LOCAL6
288: { LOG_LOCAL6, "local6" },
289: #endif
290: #ifdef LOG_LOCAL7
291: { LOG_LOCAL7, "local7" },
292: #endif
293: { -1, NULL }};
294:
295:
296: /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
297: static struct parm_struct parm_table[] =
298: {
299: {"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
300: {"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
301: {"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
302: {"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
303: {"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
304:
305: {"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
306: {"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0},
307: {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
308: {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
309: {"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
310: {"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
311: {"fake super", P_BOOL, P_LOCAL, &sDefault.fake_super, NULL,0},
312: {"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
313: {"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
314: {"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
315: {"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL,0},
316: {"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors, NULL,0},
317: {"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable,NULL,0},
318: {"include from", P_STRING, P_LOCAL, &sDefault.include_from, NULL,0},
319: {"include", P_STRING, P_LOCAL, &sDefault.include, NULL,0},
320: {"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
321: {"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
322: {"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
323: {"log file", P_STRING, P_LOCAL, &sDefault.log_file, NULL,0},
324: {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
325: {"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
326: {"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
327: {"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0},
328: {"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
329: {"numeric ids", P_BOOL, P_LOCAL, &sDefault.numeric_ids, NULL,0},
330: {"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
331: {"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
332: #ifdef HAVE_PUTENV
333: {"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec, NULL,0},
334: {"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL,0},
335: #endif
336: {"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL,0},
337: {"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
338: {"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
339: {"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
340: {"syslog facility", P_ENUM, P_LOCAL, &sDefault.syslog_facility,enum_facilities,0},
341: {"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
342: {"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
343: {"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
344: {"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL,0},
345: {"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL,0},
346: {"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL,0},
347: {NULL, P_BOOL, P_NONE, NULL, NULL,0}
348: };
349:
350:
351: /***************************************************************************
352: * Initialise the global parameter structure.
353: ***************************************************************************/
354: static void init_globals(void)
355: {
356: memset(&Globals, 0, sizeof Globals);
357: }
358:
359: /***************************************************************************
360: * Initialise the sDefault parameter structure.
361: ***************************************************************************/
362: static void init_locals(void)
363: {
364: }
365:
366:
367: /*
368: In this section all the functions that are used to access the
369: parameters from the rest of the program are defined
370: */
371:
372: #define FN_GLOBAL_STRING(fn_name,ptr) \
373: char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
374: #define FN_GLOBAL_BOOL(fn_name,ptr) \
375: BOOL fn_name(void) {return(*(BOOL *)(ptr));}
376: #define FN_GLOBAL_CHAR(fn_name,ptr) \
377: char fn_name(void) {return(*(char *)(ptr));}
378: #define FN_GLOBAL_INTEGER(fn_name,ptr) \
379: int fn_name(void) {return(*(int *)(ptr));}
380:
381: #define FN_LOCAL_STRING(fn_name,val) \
382: char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
383: #define FN_LOCAL_BOOL(fn_name,val) \
384: BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
385: #define FN_LOCAL_CHAR(fn_name,val) \
386: char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
387: #define FN_LOCAL_INTEGER(fn_name,val) \
388: int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
389:
390:
391: FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
392: FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
393: FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
394: FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
395:
396: FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
397:
398: FN_LOCAL_STRING(lp_auth_users, auth_users)
399: FN_LOCAL_STRING(lp_charset, charset)
400: FN_LOCAL_STRING(lp_comment, comment)
401: FN_LOCAL_STRING(lp_dont_compress, dont_compress)
402: FN_LOCAL_STRING(lp_exclude, exclude)
403: FN_LOCAL_STRING(lp_exclude_from, exclude_from)
404: FN_LOCAL_STRING(lp_filter, filter)
405: FN_LOCAL_STRING(lp_gid, gid)
406: FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
407: FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
408: FN_LOCAL_STRING(lp_include, include)
409: FN_LOCAL_STRING(lp_include_from, include_from)
410: FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
411: FN_LOCAL_STRING(lp_lock_file, lock_file)
412: FN_LOCAL_STRING(lp_log_file, log_file)
413: FN_LOCAL_STRING(lp_log_format, log_format)
414: FN_LOCAL_STRING(lp_name, name)
415: FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
416: FN_LOCAL_STRING(lp_path, path)
417: FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
418: FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
419: FN_LOCAL_STRING(lp_refuse_options, refuse_options)
420: FN_LOCAL_STRING(lp_secrets_file, secrets_file)
421: FN_LOCAL_STRING(lp_temp_dir, temp_dir)
422: FN_LOCAL_STRING(lp_uid, uid)
423:
424: FN_LOCAL_INTEGER(lp_max_connections, max_connections)
425: FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
426: FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
427: FN_LOCAL_INTEGER(lp_timeout, timeout)
428:
429: FN_LOCAL_BOOL(lp_fake_super, fake_super)
430: FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
431: FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
432: FN_LOCAL_BOOL(lp_list, list)
433: FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
434: FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
435: FN_LOCAL_BOOL(lp_read_only, read_only)
436: FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
437: FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
438: FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
439: FN_LOCAL_BOOL(lp_write_only, write_only)
440:
441: /* local prototypes */
442: static int strwicmp(char *psz1, char *psz2);
443: static int map_parameter(char *parmname);
444: static BOOL set_boolean(BOOL *pb, char *parmvalue);
445: static int getservicebyname(char *name, service *pserviceDest);
446: static void copy_service(service *pserviceDest, service *pserviceSource);
447: static BOOL do_parameter(char *parmname, char *parmvalue);
448: static BOOL do_section(char *sectionname);
449:
450:
451: /***************************************************************************
452: * initialise a service to the defaults
453: ***************************************************************************/
454: static void init_service(service *pservice)
455: {
456: memset((char *)pservice,0,sizeof(service));
457: copy_service(pservice,&sDefault);
458: }
459:
460:
461: /**
462: * Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
463: * be initialized when this is called, either to NULL or a malloc'd
464: * string.
465: *
466: * @fixme There is a small leak here in that sometimes the existing
467: * value will be dynamically allocated, and the old copy is lost.
468: * However, we can't always deallocate the old value, because in the
469: * case of sDefault, it points to a static string. It would be nice
470: * to have either all-strdup'd values, or to never need to free
471: * memory.
472: **/
473: static void string_set(char **s, const char *v)
474: {
475: if (!v) {
476: *s = NULL;
477: return;
478: }
479: *s = strdup(v);
480: if (!*s)
481: exit_cleanup(RERR_MALLOC);
482: }
483:
484:
485: /***************************************************************************
486: * add a new service to the services array initialising it with the given
487: * service
488: ***************************************************************************/
489: static int add_a_service(service *pservice, char *name)
490: {
491: int i;
492: service tservice;
493: int num_to_alloc = iNumServices+1;
494:
495: tservice = *pservice;
496:
497: /* it might already exist */
498: if (name)
499: {
500: i = getservicebyname(name,NULL);
501: if (i >= 0)
502: return(i);
503: }
504:
505: i = iNumServices;
506:
507: ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
508:
509: if (ServicePtrs)
510: pSERVICE(iNumServices) = new(service);
511:
512: if (!ServicePtrs || !pSERVICE(iNumServices))
513: return(-1);
514:
515: iNumServices++;
516:
517: init_service(pSERVICE(i));
518: copy_service(pSERVICE(i),&tservice);
519: if (name)
520: string_set(&iSERVICE(i).name,name);
521:
522: return(i);
523: }
524:
525: /***************************************************************************
526: * Do a case-insensitive, whitespace-ignoring string compare.
527: ***************************************************************************/
528: static int strwicmp(char *psz1, char *psz2)
529: {
530: /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
531: /* appropriate value. */
532: if (psz1 == psz2)
533: return (0);
534: else
535: if (psz1 == NULL)
536: return (-1);
537: else
538: if (psz2 == NULL)
539: return (1);
540:
541: /* sync the strings on first non-whitespace */
542: while (1)
543: {
544: while (isSpace(psz1))
545: psz1++;
546: while (isSpace(psz2))
547: psz2++;
548: if (toUpper(psz1) != toUpper(psz2) || *psz1 == '\0' || *psz2 == '\0')
549: break;
550: psz1++;
551: psz2++;
552: }
553: return (*psz1 - *psz2);
554: }
555:
556: /***************************************************************************
557: * Map a parameter's string representation to something we can use.
558: * Returns False if the parameter string is not recognised, else TRUE.
559: ***************************************************************************/
560: static int map_parameter(char *parmname)
561: {
562: int iIndex;
563:
564: if (*parmname == '-')
565: return(-1);
566:
567: for (iIndex = 0; parm_table[iIndex].label; iIndex++)
568: if (strwicmp(parm_table[iIndex].label, parmname) == 0)
569: return(iIndex);
570:
571: rprintf(FLOG, "Unknown Parameter encountered: \"%s\"\n", parmname);
572: return(-1);
573: }
574:
575:
576: /***************************************************************************
577: * Set a boolean variable from the text value stored in the passed string.
578: * Returns True in success, False if the passed string does not correctly
579: * represent a boolean.
580: ***************************************************************************/
581: static BOOL set_boolean(BOOL *pb, char *parmvalue)
582: {
583: BOOL bRetval;
584:
585: bRetval = True;
586: if (strwicmp(parmvalue, "yes") == 0 ||
587: strwicmp(parmvalue, "true") == 0 ||
588: strwicmp(parmvalue, "1") == 0)
589: *pb = True;
590: else
591: if (strwicmp(parmvalue, "no") == 0 ||
592: strwicmp(parmvalue, "False") == 0 ||
593: strwicmp(parmvalue, "0") == 0)
594: *pb = False;
595: else
596: {
597: rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n",
598: parmvalue);
599: bRetval = False;
600: }
601: return (bRetval);
602: }
603:
604: /***************************************************************************
605: * Find a service by name. Otherwise works like get_service.
606: ***************************************************************************/
607: static int getservicebyname(char *name, service *pserviceDest)
608: {
609: int iService;
610:
611: for (iService = iNumServices - 1; iService >= 0; iService--)
612: if (strwicmp(iSERVICE(iService).name, name) == 0)
613: {
614: if (pserviceDest != NULL)
615: copy_service(pserviceDest, pSERVICE(iService));
616: break;
617: }
618:
619: return (iService);
620: }
621:
622:
623:
624: /***************************************************************************
625: * Copy a service structure to another
626: ***************************************************************************/
627: static void copy_service(service *pserviceDest,
628: service *pserviceSource)
629: {
630: int i;
631:
632: for (i=0;parm_table[i].label;i++)
633: if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
634: void *def_ptr = parm_table[i].ptr;
635: void *src_ptr =
636: ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
637: void *dest_ptr =
638: ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
639:
640: switch (parm_table[i].type)
641: {
642: case P_BOOL:
643: case P_BOOLREV:
644: *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
645: break;
646:
647: case P_INTEGER:
648: case P_ENUM:
649: case P_OCTAL:
650: *(int *)dest_ptr = *(int *)src_ptr;
651: break;
652:
653: case P_CHAR:
654: *(char *)dest_ptr = *(char *)src_ptr;
655: break;
656:
657: case P_PATH:
658: case P_STRING:
659: string_set(dest_ptr,*(char **)src_ptr);
660: break;
661:
662: default:
663: break;
664: }
665: }
666: }
667:
668:
669: /***************************************************************************
670: * Process a parameter for a particular service number. If snum < 0
671: * then assume we are in the globals
672: ***************************************************************************/
673: static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
674: {
675: int parmnum, i;
676: void *parm_ptr=NULL; /* where we are going to store the result */
677: void *def_ptr=NULL;
678: char *cp;
679:
680: parmnum = map_parameter(parmname);
681:
682: if (parmnum < 0)
683: {
684: rprintf(FLOG, "IGNORING unknown parameter \"%s\"\n", parmname);
685: return(True);
686: }
687:
688: def_ptr = parm_table[parmnum].ptr;
689:
690: /* we might point at a service, the default service or a global */
691: if (snum < 0) {
692: parm_ptr = def_ptr;
693: } else {
694: if (parm_table[parmnum].class == P_GLOBAL) {
695: rprintf(FLOG, "Global parameter %s found in service section!\n",parmname);
696: return(True);
697: }
698: parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
699: }
700:
701: /* now switch on the type of variable it is */
702: switch (parm_table[parmnum].type)
703: {
704: case P_BOOL:
705: set_boolean(parm_ptr,parmvalue);
706: break;
707:
708: case P_BOOLREV:
709: set_boolean(parm_ptr,parmvalue);
710: *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
711: break;
712:
713: case P_INTEGER:
714: *(int *)parm_ptr = atoi(parmvalue);
715: break;
716:
717: case P_CHAR:
718: *(char *)parm_ptr = *parmvalue;
719: break;
720:
721: case P_OCTAL:
722: sscanf(parmvalue,"%o",(int *)parm_ptr);
723: break;
724:
725: case P_PATH:
726: string_set(parm_ptr,parmvalue);
727: if ((cp = *(char**)parm_ptr) != NULL) {
728: int len = strlen(cp);
729: while (len > 1 && cp[len-1] == '/') len--;
730: cp[len] = '\0';
731: }
732: break;
733:
734: case P_STRING:
735: string_set(parm_ptr,parmvalue);
736: break;
737:
738: case P_GSTRING:
739: strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring));
740: break;
741:
742: case P_ENUM:
743: for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
744: if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
745: *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
746: break;
747: }
748: }
749: if (!parm_table[parmnum].enum_list[i].name) {
750: if (atoi(parmvalue) > 0)
751: *(int *)parm_ptr = atoi(parmvalue);
752: }
753: break;
754: case P_SEP:
755: break;
756: }
757:
758: return(True);
759: }
760:
761: /***************************************************************************
762: * Process a parameter.
763: ***************************************************************************/
764: static BOOL do_parameter(char *parmname, char *parmvalue)
765: {
766: return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
767: }
768:
769: /***************************************************************************
770: * Process a new section (service). At this stage all sections are services.
771: * Later we'll have special sections that permit server parameters to be set.
772: * Returns True on success, False on failure.
773: ***************************************************************************/
774: static BOOL do_section(char *sectionname)
775: {
776: BOOL bRetval;
777: BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
778: bRetval = False;
779:
780: /* if we were in a global section then do the local inits */
781: if (bInGlobalSection && !isglobal)
782: init_locals();
783:
784: /* if we've just struck a global section, note the fact. */
785: bInGlobalSection = isglobal;
786:
787: /* check for multiple global sections */
788: if (bInGlobalSection)
789: {
790: return(True);
791: }
792:
793: if (strchr(sectionname, '/') != NULL) {
794: rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
795: return False;
796: }
797:
798: /* if we have a current service, tidy it up before moving on */
799: bRetval = True;
800:
801: if (iServiceIndex >= 0)
802: bRetval = True;
803:
804: /* if all is still well, move to the next record in the services array */
805: if (bRetval)
806: {
807: /* We put this here to avoid an odd message order if messages are */
808: /* issued by the post-processing of a previous section. */
809:
810: if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
811: {
812: rprintf(FLOG, "Failed to add a new service\n");
813: return(False);
814: }
815: }
816:
817: return (bRetval);
818: }
819:
820:
821: /***************************************************************************
822: * Load the services array from the services file. Return True on success,
823: * False on failure.
824: ***************************************************************************/
825: BOOL lp_load(char *pszFname, int globals_only)
826: {
827: pstring n2;
828: BOOL bRetval;
829:
830: bRetval = False;
831:
832: bInGlobalSection = True;
833:
834: init_globals();
835:
836: pstrcpy(n2, pszFname);
837:
838: /* We get sections first, so have to start 'behind' to make up */
839: iServiceIndex = -1;
840: bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
841:
842: return (bRetval);
843: }
844:
845:
846: /***************************************************************************
847: * return the max number of services
848: ***************************************************************************/
849: int lp_numservices(void)
850: {
851: return(iNumServices);
852: }
853:
854: /***************************************************************************
855: * Return the number of the service with the given name, or -1 if it doesn't
856: * exist. Note that this is a DIFFERENT ANIMAL from the internal function
857: * getservicebyname()! This works ONLY if all services have been loaded, and
858: * does not copy the found service.
859: ***************************************************************************/
860: int lp_number(char *name)
861: {
862: int iService;
863:
864: for (iService = iNumServices - 1; iService >= 0; iService--)
865: if (strcmp(lp_name(iService), name) == 0)
866: break;
867:
868: return (iService);
869: }
870:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>