X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/789213909dfbf1c1e40e67663bff386756012eb6..7766e673215542dadc066193a5a166274d00e9ab:/loadparm.c diff --git a/loadparm.c b/loadparm.c index 905a9104..965b771b 100644 --- a/loadparm.c +++ b/loadparm.c @@ -54,7 +54,8 @@ extern item_list dparam_list; #endif #define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \ - " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg" + " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg *.png" \ + " *.lzo *.rzip *.lzma *.rar *.ace *.gpg *.xz *.txz *.lz *.tlz" /* the following are used by loadparm for option lists */ typedef enum { @@ -89,23 +90,21 @@ struct parm_struct { #define LP_SNUM_OK(i) ((i) >= 0 && (i) < (int)section_list.count) #define SECTION_PTR(s, p) (((char*)(s)) + (ptrdiff_t)(((char*)(p))-(char*)&Vars.l)) -/* - * This structure describes global (ie., server-wide) parameters. - */ +/* This structure describes global (ie., server-wide) parameters. */ typedef struct { char *bind_address; char *motd_file; char *pid_file; char *socket_options; + int listen_backlog; int rsync_port; } global_vars; -/* - * This structure describes a single section. Their order must match the +/* This structure describes a single section. Their order must match the * initializers below, which you can accomplish by keeping each sub-section * sorted. (e.g. in vim, just visually select each subsection and use !sort.) - */ + * NOTE: the char* variables MUST all remain at the start of the stuct! */ typedef struct { char *auth_users; char *charset; @@ -132,6 +131,8 @@ typedef struct { char *secrets_file; char *temp_dir; char *uid; +/* NOTE: update this macro if the last char* variable changes! */ +#define LOCAL_STRING_COUNT() (offsetof(local_vars, uid) / sizeof (char*) + 1) int max_connections; int max_verbosity; @@ -139,6 +140,7 @@ typedef struct { int timeout; BOOL fake_super; + BOOL forward_lookup; BOOL ignore_errors; BOOL ignore_nonreadable; BOOL list; @@ -174,6 +176,7 @@ static const all_vars Defaults = { /* pid_file; */ NULL, /* socket_options; */ NULL, + /* listen_backlog; */ 5, /* rsync_port; */ 0, }, @@ -186,7 +189,7 @@ static const all_vars Defaults = { /* exclude; */ NULL, /* exclude_from; */ NULL, /* filter; */ NULL, - /* gid; */ NOBODY_GROUP, + /* gid; */ NULL, /* hosts_allow; */ NULL, /* hosts_deny; */ NULL, /* include; */ NULL, @@ -203,7 +206,7 @@ static const all_vars Defaults = { /* refuse_options; */ NULL, /* secrets_file; */ NULL, /* temp_dir; */ NULL, - /* uid; */ NOBODY_USER, + /* uid; */ NULL, /* max_connections; */ 0, /* max_verbosity; */ 1, @@ -211,6 +214,7 @@ static const all_vars Defaults = { /* timeout; */ 0, /* fake_super; */ False, + /* forward_lookup; */ True, /* ignore_errors; */ False, /* ignore_nonreadable; */ False, /* list; */ True, @@ -309,6 +313,7 @@ static struct enum_list enum_facilities[] = { static struct parm_struct parm_table[] = { {"address", P_STRING, P_GLOBAL,&Vars.g.bind_address, NULL,0}, + {"listen backlog", P_INTEGER,P_GLOBAL,&Vars.g.listen_backlog, NULL,0}, {"motd file", P_STRING, P_GLOBAL,&Vars.g.motd_file, NULL,0}, {"pid file", P_STRING, P_GLOBAL,&Vars.g.pid_file, NULL,0}, {"port", P_INTEGER,P_GLOBAL,&Vars.g.rsync_port, NULL,0}, @@ -322,6 +327,7 @@ static struct parm_struct parm_table[] = {"exclude", P_STRING, P_LOCAL, &Vars.l.exclude, NULL,0}, {"fake super", P_BOOL, P_LOCAL, &Vars.l.fake_super, NULL,0}, {"filter", P_STRING, P_LOCAL, &Vars.l.filter, NULL,0}, + {"forward lookup", P_BOOL, P_LOCAL, &Vars.l.forward_lookup, NULL,0}, {"gid", P_STRING, P_LOCAL, &Vars.l.gid, NULL,0}, {"hosts allow", P_STRING, P_LOCAL, &Vars.l.hosts_allow, NULL,0}, {"hosts deny", P_STRING, P_LOCAL, &Vars.l.hosts_deny, NULL,0}, @@ -366,11 +372,61 @@ static void reset_all_vars(void) memcpy(&Vars, &Defaults, sizeof Vars); } +/* Expand %VAR% references. Any unknown vars or unrecognized + * syntax leaves the raw chars unchanged. */ +static char *expand_vars(char *str) +{ + char *buf, *t, *f; + int bufsize; + + if (strchr(str, '%') == NULL) + return str; + + bufsize = strlen(str) + 2048; + if ((buf = new_array(char, bufsize+1)) == NULL) /* +1 for trailing '\0' */ + out_of_memory("expand_vars"); + + for (t = buf, f = str; bufsize && *f; ) { + if (*f == '%' && *++f != '%') { + char *percent = strchr(f, '%'); + if (percent) { + char *val; + *percent = '\0'; + val = getenv(f); + *percent = '%'; + if (val) { + int len = strlcpy(t, val, bufsize+1); + if (len > bufsize) + break; + bufsize -= len; + t += len; + f = percent + 1; + continue; + } + } + f--; + } + *t++ = *f++; + bufsize--; + } + *t = '\0'; + + if (*f) { + rprintf(FLOG, "Overflowed buf in expand_vars() trying to expand: %s\n", str); + exit_cleanup(RERR_MALLOC); + } + + if (bufsize && (buf = realloc(buf, t - buf + 1)) == NULL) + out_of_memory("expand_vars"); + + return buf; +} + /* In this section all the functions that are used to access the * parameters from the rest of the program are defined. */ #define FN_GLOBAL_STRING(fn_name, ptr) \ - char *fn_name(void) {return *(char **)(ptr) ? *(char **)(ptr) : "";} + char *fn_name(void) {return expand_vars(*(char **)(ptr) ? *(char **)(ptr) : "");} #define FN_GLOBAL_BOOL(fn_name, ptr) \ BOOL fn_name(void) {return *(BOOL *)(ptr);} #define FN_GLOBAL_CHAR(fn_name, ptr) \ @@ -379,7 +435,7 @@ static void reset_all_vars(void) int fn_name(void) {return *(int *)(ptr);} #define FN_LOCAL_STRING(fn_name, val) \ - char *fn_name(int i) {return LP_SNUM_OK(i) && iSECTION(i).val? iSECTION(i).val : (Vars.l.val? Vars.l.val : "");} + char *fn_name(int i) {return expand_vars(LP_SNUM_OK(i) && iSECTION(i).val ? iSECTION(i).val : Vars.l.val ? Vars.l.val : "");} #define FN_LOCAL_BOOL(fn_name, val) \ BOOL fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : Vars.l.val;} #define FN_LOCAL_CHAR(fn_name, val) \ @@ -392,6 +448,7 @@ FN_GLOBAL_STRING(lp_motd_file, &Vars.g.motd_file) FN_GLOBAL_STRING(lp_pid_file, &Vars.g.pid_file) FN_GLOBAL_STRING(lp_socket_options, &Vars.g.socket_options) +FN_GLOBAL_INTEGER(lp_listen_backlog, &Vars.g.listen_backlog) FN_GLOBAL_INTEGER(lp_rsync_port, &Vars.g.rsync_port) FN_LOCAL_STRING(lp_auth_users, auth_users) @@ -426,6 +483,7 @@ FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility) FN_LOCAL_INTEGER(lp_timeout, timeout) FN_LOCAL_BOOL(lp_fake_super, fake_super) +FN_LOCAL_BOOL(lp_forward_lookup, forward_lookup) FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors) FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable) FN_LOCAL_BOOL(lp_list, list) @@ -438,62 +496,31 @@ FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging) FN_LOCAL_BOOL(lp_use_chroot, use_chroot) FN_LOCAL_BOOL(lp_write_only, write_only) -/* Assign a copy of v to *s. Handles NULL strings. *v must - * be initialized when this is called, either to NULL or a malloc'd - * string. - * - * FIXME There is a small leak here in that sometimes the existing - * value will be dynamically allocated, and the old copy is lost. - * However, we can't always deallocate the old value, because the - * initial values in Defaults.l are static strings. It would be nice - * to have either all-strdup'd values, or to never need to free - * memory. */ -static void string_set(char **s, const char *v) +/* Assign a copy of v to *s. Handles NULL strings. We don't worry + * about overwriting a malloc'd string because the long-running + * (port-listening) daemon only loads the config file once, and the + * per-job (forked or xinitd-ran) daemon only re-reads the file at + * the start, so any lost memory is inconsequential. */ +static inline void string_set(char **s, const char *v) { - if (!v) { + if (!v) *s = NULL; - return; - } - if (!(*s = strdup(v))) + else if (!(*s = strdup(v))) out_of_memory("string_set"); } -/* Copy the local_vars, duplicating any strings in the source. */ +/* Copy the local_vars, strdup'ing any strings. NOTE: this depends on + * the structure starting with a contiguous list of the char* variables, + * and having an accurate count in the LOCAL_STRING_COUNT() macro. */ static void copy_section(local_vars *psectionDest, local_vars *psectionSource) { - int i; - - for (i = 0; parm_table[i].label; i++) { - if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) { - void *def_ptr = parm_table[i].ptr; - void *src_ptr = SECTION_PTR(psectionSource, def_ptr); - void *dest_ptr = SECTION_PTR(psectionDest, def_ptr); + int count = LOCAL_STRING_COUNT(); + char **strings = (char**)psectionDest; - switch (parm_table[i].type) { - case P_BOOL: - case P_BOOLREV: - *(BOOL *)dest_ptr = *(BOOL *)src_ptr; - break; - - case P_INTEGER: - case P_ENUM: - case P_OCTAL: - *(int *)dest_ptr = *(int *)src_ptr; - break; - - case P_CHAR: - *(char *)dest_ptr = *(char *)src_ptr; - break; - - case P_PATH: - case P_STRING: - string_set(dest_ptr, *(char **)src_ptr); - break; - - default: - break; - } - } + memcpy(psectionDest, psectionSource, sizeof psectionDest[0]); + while (count--) { + if (strings[count] && !(strings[count] = strdup(strings[count]))) + out_of_memory("copy_section"); } } @@ -634,6 +661,17 @@ static BOOL do_parameter(char *parmname, char *parmvalue) } /* now switch on the type of variable it is */ + switch (parm_table[parmnum].type) { + case P_PATH: + case P_STRING: + /* delay expansion of vars */ + break; + default: + /* expand any %VARS% now */ + parmvalue = expand_vars(parmvalue); + break; + } + switch (parm_table[parmnum].type) { case P_BOOL: set_boolean(parm_ptr, parmvalue);