Annotation of embedaddon/rsync/loadparm.c, revision 1.1.1.2
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.2 ! misho 20: * Copyright (C) 2003-2013 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>