Annotation of embedaddon/rsync/loadparm.c, revision 1.1.1.3
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>
1.1.1.3 ! misho 20: * Copyright (C) 2003-2015 Wayne Davison <wayned@samba.org>
1.1 misho 21: */
22:
23: /* Load parameters.
24: *
25: * This module provides suitable callback functions for the params
1.1.1.2 misho 26: * module. It builds the internal table of section details which is
1.1 misho 27: * then used by the rest of the server.
28: *
29: * To add a parameter:
30: *
1.1.1.2 misho 31: * 1) add it to the global_vars or local_vars structure definition
1.1 misho 32: * 2) add it to the parm_table
33: * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
1.1.1.2 misho 34: * 4) initialise it in the Defaults static stucture
1.1 misho 35: *
36: * Notes:
1.1.1.2 misho 37: * The configuration file is processed sequentially for speed. For this
38: * reason, there is a fair bit of sequence-dependent code here - ie., code
39: * which assumes that certain things happen before others. In particular, the
40: * code which happens at the boundary between sections is delicately poised,
41: * so be careful!
1.1 misho 42: */
43:
44: #include "rsync.h"
1.1.1.2 misho 45: #include "itypes.h"
46:
47: extern item_list dparam_list;
48:
49: #define strequal(a, b) (strcasecmp(a, b)==0)
1.1 misho 50: #define BOOLSTR(b) ((b) ? "Yes" : "No")
51:
52: #ifndef LOG_DAEMON
53: #define LOG_DAEMON 0
54: #endif
55:
56: #define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
1.1.1.2 misho 57: " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg *.png" \
58: " *.lzo *.rzip *.lzma *.rar *.ace *.gpg *.xz *.txz *.lz *.tlz"
1.1 misho 59:
60: /* the following are used by loadparm for option lists */
1.1.1.2 misho 61: typedef enum {
62: P_BOOL, P_BOOLREV, P_CHAR, P_INTEGER,
63: P_OCTAL, P_PATH, P_STRING, P_ENUM
1.1 misho 64: } parm_type;
65:
1.1.1.2 misho 66: typedef enum {
67: P_LOCAL, P_GLOBAL, P_NONE
1.1 misho 68: } parm_class;
69:
70: struct enum_list {
71: int value;
72: char *name;
73: };
74:
1.1.1.2 misho 75: struct parm_struct {
1.1 misho 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: #ifndef GLOBAL_NAME
85: #define GLOBAL_NAME "global"
86: #endif
87:
88: /* some helpful bits */
1.1.1.2 misho 89: #define iSECTION(i) ((local_vars*)section_list.items)[i]
90: #define LP_SNUM_OK(i) ((i) >= 0 && (i) < (int)section_list.count)
91: #define SECTION_PTR(s, p) (((char*)(s)) + (ptrdiff_t)(((char*)(p))-(char*)&Vars.l))
1.1 misho 92:
1.1.1.2 misho 93: /* This structure describes global (ie., server-wide) parameters. */
94: typedef struct {
1.1 misho 95: char *bind_address;
96: char *motd_file;
97: char *pid_file;
98: char *socket_options;
99:
1.1.1.2 misho 100: int listen_backlog;
1.1 misho 101: int rsync_port;
1.1.1.2 misho 102: } global_vars;
1.1 misho 103:
1.1.1.2 misho 104: /* This structure describes a single section. Their order must match the
1.1 misho 105: * initializers below, which you can accomplish by keeping each sub-section
106: * sorted. (e.g. in vim, just visually select each subsection and use !sort.)
1.1.1.2 misho 107: * NOTE: the char* variables MUST all remain at the start of the stuct! */
108: typedef struct {
1.1 misho 109: char *auth_users;
110: char *charset;
111: char *comment;
112: char *dont_compress;
113: char *exclude;
114: char *exclude_from;
115: char *filter;
116: char *gid;
117: char *hosts_allow;
118: char *hosts_deny;
119: char *include;
120: char *include_from;
121: char *incoming_chmod;
122: char *lock_file;
123: char *log_file;
124: char *log_format;
125: char *name;
126: char *outgoing_chmod;
127: char *path;
128: char *postxfer_exec;
129: char *prexfer_exec;
130: char *refuse_options;
131: char *secrets_file;
132: char *temp_dir;
133: char *uid;
1.1.1.2 misho 134: /* NOTE: update this macro if the last char* variable changes! */
135: #define LOCAL_STRING_COUNT() (offsetof(local_vars, uid) / sizeof (char*) + 1)
1.1 misho 136:
137: int max_connections;
138: int max_verbosity;
139: int syslog_facility;
140: int timeout;
141:
142: BOOL fake_super;
1.1.1.2 misho 143: BOOL forward_lookup;
1.1 misho 144: BOOL ignore_errors;
145: BOOL ignore_nonreadable;
146: BOOL list;
147: BOOL munge_symlinks;
148: BOOL numeric_ids;
149: BOOL read_only;
1.1.1.2 misho 150: BOOL reverse_lookup;
1.1 misho 151: BOOL strict_modes;
152: BOOL transfer_logging;
153: BOOL use_chroot;
154: BOOL write_only;
1.1.1.2 misho 155: } local_vars;
1.1 misho 156:
1.1.1.2 misho 157: /* This structure describes the global variables (g) as well as the globally
158: * specified values of the local variables (l), which are used when modules
159: * don't specify their own values. */
160: typedef struct {
161: global_vars g;
162: local_vars l;
163: } all_vars;
1.1 misho 164:
1.1.1.2 misho 165: /* The application defaults for all the variables. "Defaults" is
166: * used to re-initialize "Vars" before each config-file read.
167: *
168: * In order to keep these sorted in the same way as the structure
1.1 misho 169: * above, use the variable name in the leading comment, including a
170: * trailing ';' (to avoid a sorting problem with trailing digits). */
1.1.1.2 misho 171: static const all_vars Defaults = {
172: /* ==== global_vars ==== */
173: {
174: /* bind_address; */ NULL,
175: /* motd_file; */ NULL,
176: /* pid_file; */ NULL,
177: /* socket_options; */ NULL,
178:
179: /* listen_backlog; */ 5,
180: /* rsync_port; */ 0,
181: },
182:
183: /* ==== local_vars ==== */
184: {
1.1 misho 185: /* auth_users; */ NULL,
186: /* charset; */ NULL,
187: /* comment; */ NULL,
188: /* dont_compress; */ DEFAULT_DONT_COMPRESS,
189: /* exclude; */ NULL,
190: /* exclude_from; */ NULL,
191: /* filter; */ NULL,
1.1.1.2 misho 192: /* gid; */ NULL,
1.1 misho 193: /* hosts_allow; */ NULL,
194: /* hosts_deny; */ NULL,
195: /* include; */ NULL,
196: /* include_from; */ NULL,
197: /* incoming_chmod; */ NULL,
198: /* lock_file; */ DEFAULT_LOCK_FILE,
199: /* log_file; */ NULL,
200: /* log_format; */ "%o %h [%a] %m (%u) %f %l",
201: /* name; */ NULL,
202: /* outgoing_chmod; */ NULL,
203: /* path; */ NULL,
204: /* postxfer_exec; */ NULL,
205: /* prexfer_exec; */ NULL,
206: /* refuse_options; */ NULL,
207: /* secrets_file; */ NULL,
208: /* temp_dir; */ NULL,
1.1.1.2 misho 209: /* uid; */ NULL,
1.1 misho 210:
211: /* max_connections; */ 0,
212: /* max_verbosity; */ 1,
213: /* syslog_facility; */ LOG_DAEMON,
214: /* timeout; */ 0,
215:
216: /* fake_super; */ False,
1.1.1.2 misho 217: /* forward_lookup; */ True,
1.1 misho 218: /* ignore_errors; */ False,
219: /* ignore_nonreadable; */ False,
220: /* list; */ True,
221: /* munge_symlinks; */ (BOOL)-1,
222: /* numeric_ids; */ (BOOL)-1,
223: /* read_only; */ True,
1.1.1.2 misho 224: /* reverse_lookup; */ True,
1.1 misho 225: /* strict_modes; */ True,
226: /* transfer_logging; */ False,
227: /* use_chroot; */ True,
228: /* write_only; */ False,
1.1.1.2 misho 229: }
1.1 misho 230: };
231:
1.1.1.2 misho 232: /* The currently configured values for all the variables. */
233: static all_vars Vars;
1.1 misho 234:
1.1.1.2 misho 235: /* Stack of "Vars" values used by the &include directive. */
236: static item_list Vars_stack = EMPTY_ITEM_LIST;
1.1 misho 237:
1.1.1.2 misho 238: /* The array of section values that holds all the defined modules. */
239: static item_list section_list = EMPTY_ITEM_LIST;
240:
241: static int iSectionIndex = -1;
1.1 misho 242: static BOOL bInGlobalSection = True;
243:
1.1.1.2 misho 244: #define NUMPARAMETERS (sizeof (parm_table) / sizeof (struct parm_struct))
1.1 misho 245:
246: static struct enum_list enum_facilities[] = {
247: #ifdef LOG_AUTH
248: { LOG_AUTH, "auth" },
249: #endif
250: #ifdef LOG_AUTHPRIV
251: { LOG_AUTHPRIV, "authpriv" },
252: #endif
253: #ifdef LOG_CRON
254: { LOG_CRON, "cron" },
255: #endif
256: #ifdef LOG_DAEMON
257: { LOG_DAEMON, "daemon" },
258: #endif
259: #ifdef LOG_FTP
260: { LOG_FTP, "ftp" },
261: #endif
262: #ifdef LOG_KERN
263: { LOG_KERN, "kern" },
264: #endif
265: #ifdef LOG_LPR
266: { LOG_LPR, "lpr" },
267: #endif
268: #ifdef LOG_MAIL
269: { LOG_MAIL, "mail" },
270: #endif
271: #ifdef LOG_NEWS
272: { LOG_NEWS, "news" },
273: #endif
274: #ifdef LOG_AUTH
275: { LOG_AUTH, "security" },
276: #endif
277: #ifdef LOG_SYSLOG
278: { LOG_SYSLOG, "syslog" },
279: #endif
280: #ifdef LOG_USER
281: { LOG_USER, "user" },
282: #endif
283: #ifdef LOG_UUCP
284: { LOG_UUCP, "uucp" },
285: #endif
286: #ifdef LOG_LOCAL0
287: { LOG_LOCAL0, "local0" },
288: #endif
289: #ifdef LOG_LOCAL1
290: { LOG_LOCAL1, "local1" },
291: #endif
292: #ifdef LOG_LOCAL2
293: { LOG_LOCAL2, "local2" },
294: #endif
295: #ifdef LOG_LOCAL3
296: { LOG_LOCAL3, "local3" },
297: #endif
298: #ifdef LOG_LOCAL4
299: { LOG_LOCAL4, "local4" },
300: #endif
301: #ifdef LOG_LOCAL5
302: { LOG_LOCAL5, "local5" },
303: #endif
304: #ifdef LOG_LOCAL6
305: { LOG_LOCAL6, "local6" },
306: #endif
307: #ifdef LOG_LOCAL7
308: { LOG_LOCAL7, "local7" },
309: #endif
1.1.1.2 misho 310: { -1, NULL }
311: };
1.1 misho 312:
313: static struct parm_struct parm_table[] =
314: {
1.1.1.2 misho 315: {"address", P_STRING, P_GLOBAL,&Vars.g.bind_address, NULL,0},
316: {"listen backlog", P_INTEGER,P_GLOBAL,&Vars.g.listen_backlog, NULL,0},
317: {"motd file", P_STRING, P_GLOBAL,&Vars.g.motd_file, NULL,0},
318: {"pid file", P_STRING, P_GLOBAL,&Vars.g.pid_file, NULL,0},
319: {"port", P_INTEGER,P_GLOBAL,&Vars.g.rsync_port, NULL,0},
320: {"socket options", P_STRING, P_GLOBAL,&Vars.g.socket_options, NULL,0},
321:
322: {"auth users", P_STRING, P_LOCAL, &Vars.l.auth_users, NULL,0},
323: {"charset", P_STRING, P_LOCAL, &Vars.l.charset, NULL,0},
324: {"comment", P_STRING, P_LOCAL, &Vars.l.comment, NULL,0},
325: {"dont compress", P_STRING, P_LOCAL, &Vars.l.dont_compress, NULL,0},
326: {"exclude from", P_STRING, P_LOCAL, &Vars.l.exclude_from, NULL,0},
327: {"exclude", P_STRING, P_LOCAL, &Vars.l.exclude, NULL,0},
328: {"fake super", P_BOOL, P_LOCAL, &Vars.l.fake_super, NULL,0},
329: {"filter", P_STRING, P_LOCAL, &Vars.l.filter, NULL,0},
330: {"forward lookup", P_BOOL, P_LOCAL, &Vars.l.forward_lookup, NULL,0},
331: {"gid", P_STRING, P_LOCAL, &Vars.l.gid, NULL,0},
332: {"hosts allow", P_STRING, P_LOCAL, &Vars.l.hosts_allow, NULL,0},
333: {"hosts deny", P_STRING, P_LOCAL, &Vars.l.hosts_deny, NULL,0},
334: {"ignore errors", P_BOOL, P_LOCAL, &Vars.l.ignore_errors, NULL,0},
335: {"ignore nonreadable",P_BOOL, P_LOCAL, &Vars.l.ignore_nonreadable, NULL,0},
336: {"include from", P_STRING, P_LOCAL, &Vars.l.include_from, NULL,0},
337: {"include", P_STRING, P_LOCAL, &Vars.l.include, NULL,0},
338: {"incoming chmod", P_STRING, P_LOCAL, &Vars.l.incoming_chmod, NULL,0},
339: {"list", P_BOOL, P_LOCAL, &Vars.l.list, NULL,0},
340: {"lock file", P_STRING, P_LOCAL, &Vars.l.lock_file, NULL,0},
341: {"log file", P_STRING, P_LOCAL, &Vars.l.log_file, NULL,0},
342: {"log format", P_STRING, P_LOCAL, &Vars.l.log_format, NULL,0},
343: {"max connections", P_INTEGER,P_LOCAL, &Vars.l.max_connections, NULL,0},
344: {"max verbosity", P_INTEGER,P_LOCAL, &Vars.l.max_verbosity, NULL,0},
345: {"munge symlinks", P_BOOL, P_LOCAL, &Vars.l.munge_symlinks, NULL,0},
346: {"name", P_STRING, P_LOCAL, &Vars.l.name, NULL,0},
347: {"numeric ids", P_BOOL, P_LOCAL, &Vars.l.numeric_ids, NULL,0},
348: {"outgoing chmod", P_STRING, P_LOCAL, &Vars.l.outgoing_chmod, NULL,0},
349: {"path", P_PATH, P_LOCAL, &Vars.l.path, NULL,0},
1.1 misho 350: #ifdef HAVE_PUTENV
1.1.1.2 misho 351: {"post-xfer exec", P_STRING, P_LOCAL, &Vars.l.postxfer_exec, NULL,0},
352: {"pre-xfer exec", P_STRING, P_LOCAL, &Vars.l.prexfer_exec, NULL,0},
1.1 misho 353: #endif
1.1.1.2 misho 354: {"read only", P_BOOL, P_LOCAL, &Vars.l.read_only, NULL,0},
355: {"refuse options", P_STRING, P_LOCAL, &Vars.l.refuse_options, NULL,0},
356: {"reverse lookup", P_BOOL, P_LOCAL, &Vars.l.reverse_lookup, NULL,0},
357: {"secrets file", P_STRING, P_LOCAL, &Vars.l.secrets_file, NULL,0},
358: {"strict modes", P_BOOL, P_LOCAL, &Vars.l.strict_modes, NULL,0},
359: {"syslog facility", P_ENUM, P_LOCAL, &Vars.l.syslog_facility, enum_facilities,0},
360: {"temp dir", P_PATH, P_LOCAL, &Vars.l.temp_dir, NULL,0},
361: {"timeout", P_INTEGER,P_LOCAL, &Vars.l.timeout, NULL,0},
362: {"transfer logging", P_BOOL, P_LOCAL, &Vars.l.transfer_logging, NULL,0},
363: {"uid", P_STRING, P_LOCAL, &Vars.l.uid, NULL,0},
364: {"use chroot", P_BOOL, P_LOCAL, &Vars.l.use_chroot, NULL,0},
365: {"write only", P_BOOL, P_LOCAL, &Vars.l.write_only, NULL,0},
1.1 misho 366: {NULL, P_BOOL, P_NONE, NULL, NULL,0}
367: };
368:
1.1.1.2 misho 369: /* Initialise the Default all_vars structure. */
370: static void reset_all_vars(void)
1.1 misho 371: {
1.1.1.2 misho 372: memcpy(&Vars, &Defaults, sizeof Vars);
1.1 misho 373: }
374:
1.1.1.2 misho 375: /* Expand %VAR% references. Any unknown vars or unrecognized
376: * syntax leaves the raw chars unchanged. */
377: static char *expand_vars(char *str)
378: {
379: char *buf, *t, *f;
380: int bufsize;
381:
382: if (strchr(str, '%') == NULL)
383: return str;
384:
385: bufsize = strlen(str) + 2048;
386: if ((buf = new_array(char, bufsize+1)) == NULL) /* +1 for trailing '\0' */
387: out_of_memory("expand_vars");
388:
389: for (t = buf, f = str; bufsize && *f; ) {
390: if (*f == '%' && *++f != '%') {
391: char *percent = strchr(f, '%');
392: if (percent) {
393: char *val;
394: *percent = '\0';
395: val = getenv(f);
396: *percent = '%';
397: if (val) {
398: int len = strlcpy(t, val, bufsize+1);
399: if (len > bufsize)
400: break;
401: bufsize -= len;
402: t += len;
403: f = percent + 1;
404: continue;
405: }
406: }
407: f--;
408: }
409: *t++ = *f++;
410: bufsize--;
411: }
412: *t = '\0';
1.1 misho 413:
1.1.1.2 misho 414: if (*f) {
415: rprintf(FLOG, "Overflowed buf in expand_vars() trying to expand: %s\n", str);
416: exit_cleanup(RERR_MALLOC);
417: }
1.1 misho 418:
1.1.1.2 misho 419: if (bufsize && (buf = realloc(buf, t - buf + 1)) == NULL)
420: out_of_memory("expand_vars");
1.1 misho 421:
1.1.1.2 misho 422: return buf;
423: }
1.1 misho 424:
1.1.1.2 misho 425: /* In this section all the functions that are used to access the
426: * parameters from the rest of the program are defined. */
1.1 misho 427:
1.1.1.2 misho 428: #define FN_GLOBAL_STRING(fn_name, ptr) \
429: char *fn_name(void) {return expand_vars(*(char **)(ptr) ? *(char **)(ptr) : "");}
430: #define FN_GLOBAL_BOOL(fn_name, ptr) \
431: BOOL fn_name(void) {return *(BOOL *)(ptr);}
432: #define FN_GLOBAL_CHAR(fn_name, ptr) \
433: char fn_name(void) {return *(char *)(ptr);}
434: #define FN_GLOBAL_INTEGER(fn_name, ptr) \
435: int fn_name(void) {return *(int *)(ptr);}
436:
437: #define FN_LOCAL_STRING(fn_name, val) \
438: char *fn_name(int i) {return expand_vars(LP_SNUM_OK(i) && iSECTION(i).val ? iSECTION(i).val : Vars.l.val ? Vars.l.val : "");}
439: #define FN_LOCAL_BOOL(fn_name, val) \
440: BOOL fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : Vars.l.val;}
441: #define FN_LOCAL_CHAR(fn_name, val) \
442: char fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : Vars.l.val;}
443: #define FN_LOCAL_INTEGER(fn_name, val) \
444: int fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : Vars.l.val;}
445:
446: FN_GLOBAL_STRING(lp_bind_address, &Vars.g.bind_address)
447: FN_GLOBAL_STRING(lp_motd_file, &Vars.g.motd_file)
448: FN_GLOBAL_STRING(lp_pid_file, &Vars.g.pid_file)
449: FN_GLOBAL_STRING(lp_socket_options, &Vars.g.socket_options)
1.1 misho 450:
1.1.1.2 misho 451: FN_GLOBAL_INTEGER(lp_listen_backlog, &Vars.g.listen_backlog)
452: FN_GLOBAL_INTEGER(lp_rsync_port, &Vars.g.rsync_port)
1.1 misho 453:
454: FN_LOCAL_STRING(lp_auth_users, auth_users)
455: FN_LOCAL_STRING(lp_charset, charset)
456: FN_LOCAL_STRING(lp_comment, comment)
457: FN_LOCAL_STRING(lp_dont_compress, dont_compress)
458: FN_LOCAL_STRING(lp_exclude, exclude)
459: FN_LOCAL_STRING(lp_exclude_from, exclude_from)
460: FN_LOCAL_STRING(lp_filter, filter)
461: FN_LOCAL_STRING(lp_gid, gid)
462: FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
463: FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
464: FN_LOCAL_STRING(lp_include, include)
465: FN_LOCAL_STRING(lp_include_from, include_from)
466: FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
467: FN_LOCAL_STRING(lp_lock_file, lock_file)
468: FN_LOCAL_STRING(lp_log_file, log_file)
469: FN_LOCAL_STRING(lp_log_format, log_format)
470: FN_LOCAL_STRING(lp_name, name)
471: FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
472: FN_LOCAL_STRING(lp_path, path)
473: FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
474: FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
475: FN_LOCAL_STRING(lp_refuse_options, refuse_options)
476: FN_LOCAL_STRING(lp_secrets_file, secrets_file)
477: FN_LOCAL_STRING(lp_temp_dir, temp_dir)
478: FN_LOCAL_STRING(lp_uid, uid)
479:
480: FN_LOCAL_INTEGER(lp_max_connections, max_connections)
481: FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
482: FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
483: FN_LOCAL_INTEGER(lp_timeout, timeout)
484:
485: FN_LOCAL_BOOL(lp_fake_super, fake_super)
1.1.1.2 misho 486: FN_LOCAL_BOOL(lp_forward_lookup, forward_lookup)
1.1 misho 487: FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
488: FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
489: FN_LOCAL_BOOL(lp_list, list)
490: FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
491: FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
492: FN_LOCAL_BOOL(lp_read_only, read_only)
1.1.1.2 misho 493: FN_LOCAL_BOOL(lp_reverse_lookup, reverse_lookup)
1.1 misho 494: FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
495: FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
496: FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
497: FN_LOCAL_BOOL(lp_write_only, write_only)
498:
1.1.1.2 misho 499: /* Assign a copy of v to *s. Handles NULL strings. We don't worry
500: * about overwriting a malloc'd string because the long-running
501: * (port-listening) daemon only loads the config file once, and the
502: * per-job (forked or xinitd-ran) daemon only re-reads the file at
503: * the start, so any lost memory is inconsequential. */
504: static inline void string_set(char **s, const char *v)
1.1 misho 505: {
1.1.1.2 misho 506: if (!v)
1.1 misho 507: *s = NULL;
1.1.1.2 misho 508: else if (!(*s = strdup(v)))
509: out_of_memory("string_set");
1.1 misho 510: }
511:
1.1.1.2 misho 512: /* Copy the local_vars, strdup'ing any strings. NOTE: this depends on
513: * the structure starting with a contiguous list of the char* variables,
514: * and having an accurate count in the LOCAL_STRING_COUNT() macro. */
515: static void copy_section(local_vars *psectionDest, local_vars *psectionSource)
516: {
517: int count = LOCAL_STRING_COUNT();
518: char **strings = (char**)psectionDest;
519:
520: memcpy(psectionDest, psectionSource, sizeof psectionDest[0]);
521: while (count--) {
522: if (strings[count] && !(strings[count] = strdup(strings[count])))
523: out_of_memory("copy_section");
524: }
525: }
1.1 misho 526:
1.1.1.2 misho 527: /* Initialise a section to the defaults. */
528: static void init_section(local_vars *psection)
1.1 misho 529: {
1.1.1.2 misho 530: memset(psection, 0, sizeof (local_vars));
531: copy_section(psection, &Vars.l);
532: }
1.1 misho 533:
1.1.1.2 misho 534: /* Do a case-insensitive, whitespace-ignoring string compare. */
535: static int strwicmp(char *psz1, char *psz2)
536: {
537: /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
538: /* appropriate value. */
539: if (psz1 == psz2)
540: return 0;
541:
542: if (psz1 == NULL)
543: return -1;
544:
545: if (psz2 == NULL)
546: return 1;
547:
548: /* sync the strings on first non-whitespace */
549: while (1) {
550: while (isSpace(psz1))
551: psz1++;
552: while (isSpace(psz2))
553: psz2++;
554: if (toUpper(psz1) != toUpper(psz2) || *psz1 == '\0' || *psz2 == '\0')
555: break;
556: psz1++;
557: psz2++;
558: }
559: return *psz1 - *psz2;
560: }
1.1 misho 561:
1.1.1.2 misho 562: /* Find a section by name. Otherwise works like get_section. */
563: static int getsectionbyname(char *name)
564: {
565: int i;
1.1 misho 566:
1.1.1.2 misho 567: for (i = section_list.count - 1; i >= 0; i--) {
568: if (strwicmp(iSECTION(i).name, name) == 0)
569: break;
570: }
1.1 misho 571:
1.1.1.2 misho 572: return i;
573: }
1.1 misho 574:
1.1.1.2 misho 575: /* Add a new section to the sections array w/the default values. */
576: static int add_a_section(char *name)
577: {
578: int i;
579: local_vars *s;
1.1 misho 580:
1.1.1.2 misho 581: /* it might already exist */
582: if (name) {
583: i = getsectionbyname(name);
584: if (i >= 0)
585: return i;
586: }
1.1 misho 587:
1.1.1.2 misho 588: i = section_list.count;
589: s = EXPAND_ITEM_LIST(§ion_list, local_vars, 2);
1.1 misho 590:
1.1.1.2 misho 591: init_section(s);
592: if (name)
593: string_set(&s->name, name);
1.1 misho 594:
1.1.1.2 misho 595: return i;
1.1 misho 596: }
597:
1.1.1.2 misho 598: /* Map a parameter's string representation to something we can use.
599: * Returns False if the parameter string is not recognised, else TRUE. */
1.1 misho 600: static int map_parameter(char *parmname)
601: {
1.1.1.2 misho 602: int iIndex;
1.1 misho 603:
1.1.1.2 misho 604: if (*parmname == '-')
605: return -1;
1.1 misho 606:
1.1.1.2 misho 607: for (iIndex = 0; parm_table[iIndex].label; iIndex++) {
608: if (strwicmp(parm_table[iIndex].label, parmname) == 0)
609: return iIndex;
610: }
1.1 misho 611:
1.1.1.2 misho 612: rprintf(FLOG, "Unknown Parameter encountered: \"%s\"\n", parmname);
613: return -1;
1.1 misho 614: }
615:
1.1.1.2 misho 616: /* Set a boolean variable from the text value stored in the passed string.
617: * Returns True in success, False if the passed string does not correctly
618: * represent a boolean. */
1.1 misho 619: static BOOL set_boolean(BOOL *pb, char *parmvalue)
620: {
1.1.1.2 misho 621: if (strwicmp(parmvalue, "yes") == 0
622: || strwicmp(parmvalue, "true") == 0
623: || strwicmp(parmvalue, "1") == 0)
624: *pb = True;
625: else if (strwicmp(parmvalue, "no") == 0
626: || strwicmp(parmvalue, "False") == 0
627: || strwicmp(parmvalue, "0") == 0)
628: *pb = False;
629: else {
630: rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n", parmvalue);
631: return False;
632: }
633: return True;
634: }
1.1 misho 635:
1.1.1.2 misho 636: /* Process a parameter. */
1.1 misho 637: static BOOL do_parameter(char *parmname, char *parmvalue)
638: {
1.1.1.2 misho 639: int parmnum, i;
640: void *parm_ptr; /* where we are going to store the result */
641: void *def_ptr;
642: char *cp;
643:
644: parmnum = map_parameter(parmname);
645:
646: if (parmnum < 0) {
647: rprintf(FLOG, "IGNORING unknown parameter \"%s\"\n", parmname);
648: return True;
649: }
650:
651: def_ptr = parm_table[parmnum].ptr;
652:
653: if (bInGlobalSection)
654: parm_ptr = def_ptr;
655: else {
656: if (parm_table[parmnum].class == P_GLOBAL) {
657: rprintf(FLOG, "Global parameter %s found in module section!\n", parmname);
658: return True;
659: }
660: parm_ptr = SECTION_PTR(&iSECTION(iSectionIndex), def_ptr);
661: }
662:
663: /* now switch on the type of variable it is */
664: switch (parm_table[parmnum].type) {
665: case P_PATH:
666: case P_STRING:
667: /* delay expansion of vars */
668: break;
669: default:
670: /* expand any %VARS% now */
671: parmvalue = expand_vars(parmvalue);
672: break;
673: }
674:
675: switch (parm_table[parmnum].type) {
676: case P_BOOL:
677: set_boolean(parm_ptr, parmvalue);
678: break;
679:
680: case P_BOOLREV:
681: set_boolean(parm_ptr, parmvalue);
682: *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
683: break;
684:
685: case P_INTEGER:
686: *(int *)parm_ptr = atoi(parmvalue);
687: break;
688:
689: case P_CHAR:
690: *(char *)parm_ptr = *parmvalue;
691: break;
692:
693: case P_OCTAL:
694: sscanf(parmvalue, "%o", (int *)parm_ptr);
695: break;
696:
697: case P_PATH:
698: string_set(parm_ptr, parmvalue);
699: if ((cp = *(char**)parm_ptr) != NULL) {
700: int len = strlen(cp);
701: while (len > 1 && cp[len-1] == '/') len--;
702: cp[len] = '\0';
703: }
704: break;
705:
706: case P_STRING:
707: string_set(parm_ptr, parmvalue);
708: break;
709:
710: case P_ENUM:
711: for (i=0; parm_table[parmnum].enum_list[i].name; i++) {
712: if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
713: *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
714: break;
715: }
716: }
717: if (!parm_table[parmnum].enum_list[i].name) {
718: if (atoi(parmvalue) > 0)
719: *(int *)parm_ptr = atoi(parmvalue);
720: }
721: break;
722: }
723:
724: return True;
1.1 misho 725: }
726:
1.1.1.2 misho 727: /* Process a new section (rsync module).
728: * Returns True on success, False on failure. */
1.1 misho 729: static BOOL do_section(char *sectionname)
730: {
1.1.1.2 misho 731: BOOL isglobal;
1.1 misho 732:
1.1.1.2 misho 733: if (*sectionname == ']') { /* A special push/pop/reset directive from params.c */
734: bInGlobalSection = 1;
735: if (strcmp(sectionname+1, "push") == 0) {
736: all_vars *vp = EXPAND_ITEM_LIST(&Vars_stack, all_vars, 2);
737: memcpy(vp, &Vars, sizeof Vars);
738: } else if (strcmp(sectionname+1, "pop") == 0
739: || strcmp(sectionname+1, "reset") == 0) {
740: all_vars *vp = ((all_vars*)Vars_stack.items) + Vars_stack.count - 1;
741: if (!Vars_stack.count)
742: return False;
743: memcpy(&Vars, vp, sizeof Vars);
744: if (sectionname[1] == 'p')
745: Vars_stack.count--;
746: } else
747: return False;
748: return True;
749: }
1.1 misho 750:
1.1.1.2 misho 751: isglobal = strwicmp(sectionname, GLOBAL_NAME) == 0;
1.1 misho 752:
1.1.1.2 misho 753: /* At the end of the global section, add any --dparam items. */
754: if (bInGlobalSection && !isglobal) {
755: if (!section_list.count)
756: set_dparams(0);
757: }
1.1 misho 758:
1.1.1.2 misho 759: /* if we've just struck a global section, note the fact. */
760: bInGlobalSection = isglobal;
1.1 misho 761:
1.1.1.2 misho 762: /* check for multiple global sections */
763: if (bInGlobalSection)
764: return True;
765:
766: #if 0
767: /* If we have a current section, tidy it up before moving on. */
768: if (iSectionIndex >= 0) {
769: /* Add any tidy work as needed ... */
770: if (problem)
771: return False;
772: }
773: #endif
1.1 misho 774:
1.1.1.2 misho 775: if (strchr(sectionname, '/') != NULL) {
776: rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
777: return False;
778: }
1.1 misho 779:
1.1.1.2 misho 780: if ((iSectionIndex = add_a_section(sectionname)) < 0) {
781: rprintf(FLOG, "Failed to add a new module\n");
782: bInGlobalSection = True;
783: return False;
784: }
1.1 misho 785:
1.1.1.2 misho 786: return True;
1.1 misho 787: }
788:
1.1.1.2 misho 789: /* Load the modules from the config file. Return True on success,
790: * False on failure. */
791: int lp_load(char *pszFname, int globals_only)
1.1 misho 792: {
793: bInGlobalSection = True;
794:
1.1.1.2 misho 795: reset_all_vars();
1.1 misho 796:
1.1.1.2 misho 797: /* We get sections first, so have to start 'behind' to make up. */
798: iSectionIndex = -1;
799: return pm_process(pszFname, globals_only ? NULL : do_section, do_parameter);
800: }
801:
802: BOOL set_dparams(int syntax_check_only)
803: {
804: char *equal, *val, **params = dparam_list.items;
805: unsigned j;
806:
807: for (j = 0; j < dparam_list.count; j++) {
808: equal = strchr(params[j], '='); /* options.c verified this */
809: *equal = '\0';
810: if (syntax_check_only) {
811: if (map_parameter(params[j]) < 0) {
812: rprintf(FERROR, "Unknown parameter \"%s\"\n", params[j]);
813: *equal = '=';
814: return False;
815: }
816: } else {
817: for (val = equal+1; isSpace(val); val++) {}
818: do_parameter(params[j], val);
819: }
820: *equal = '=';
821: }
1.1 misho 822:
1.1.1.2 misho 823: return True;
1.1 misho 824: }
825:
1.1.1.2 misho 826: /* Return the max number of modules (sections). */
827: int lp_num_modules(void)
1.1 misho 828: {
1.1.1.2 misho 829: return section_list.count;
1.1 misho 830: }
831:
1.1.1.2 misho 832: /* Return the number of the module with the given name, or -1 if it doesn't
833: * exist. Note that this is a DIFFERENT ANIMAL from the internal function
834: * getsectionbyname()! This works ONLY if all sections have been loaded,
835: * and does not copy the found section. */
1.1 misho 836: int lp_number(char *name)
837: {
1.1.1.2 misho 838: int i;
1.1 misho 839:
1.1.1.2 misho 840: for (i = section_list.count - 1; i >= 0; i--) {
841: if (strcmp(lp_name(i), name) == 0)
842: break;
843: }
1.1 misho 844:
1.1.1.2 misho 845: return i;
1.1 misho 846: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>