--- autofs-5.0.1/modules/lookup_file.c.consistent-dquote-handling 2007-05-04 13:40:48.000000000 +0800 +++ autofs-5.0.1/modules/lookup_file.c 2007-05-04 13:41:52.000000000 +0800 @@ -41,7 +41,7 @@ } LOOKUP_STATE; typedef enum { got_nothing, got_star, got_real, got_plus } FOUND_STATE; -typedef enum { esc_none, esc_char, esc_val } ESCAPES; +typedef enum { esc_none, esc_char, esc_val, esc_all } ESCAPES; struct lookup_context { @@ -143,6 +143,8 @@ ungetc(nch, f); escape = esc_char; } + if (ch == '"') + escape = esc_all; break; case esc_char: @@ -152,6 +154,11 @@ case esc_val: escape = esc_none; break; + + case esc_all: + if (ch == '"') + escape = esc_none; + break; } switch (state) { @@ -171,6 +178,10 @@ *(kptr++) = ch; key_len++; } + } else if (escape == esc_all) { + state = st_compare; + *(kptr++) = ch; + key_len++; } else if (escape == esc_char); else state = st_badent; @@ -181,7 +192,11 @@ state = st_begin; if (gotten == got_plus) goto got_it; - if (escape != esc_val) + else if (escape == esc_all) { + warn(LOGOPT_ANY, MODPREFIX + "unmatched \" in map key %s", key); + goto next; + } else if (escape != esc_val) goto got_it; } else if (isspace(ch) && !escape) { getting = got_real; @@ -199,6 +214,10 @@ "length is %d", key, KEY_MAX_LEN); } else { + if (escape == esc_val) { + *(kptr++) = '\\'; + key_len++; + } *(kptr++) = ch; key_len++; } @@ -237,9 +256,12 @@ break; } p = mapent; - *(p++) = '\\'; + if (escape == esc_val) { + *(p++) = '\\'; + mapent_len++; + } *(p++) = ch; - mapent_len = 2; + mapent_len++; } else { p = mapent; *(p++) = ch; @@ -264,6 +286,12 @@ } ungetc(nch, f); state = st_begin; + if (escape == esc_all) { + warn(LOGOPT_ANY, MODPREFIX + "unmatched \" in %s for key %s", + mapent, key); + goto next; + } if (gotten == got_real || gotten == getting) goto got_it; } else if (mapent_len < MAPENT_MAX_LEN) { --- autofs-5.0.1/modules/parse_sun.c.consistent-dquote-handling 2007-05-04 13:40:48.000000000 +0800 +++ autofs-5.0.1/modules/parse_sun.c 2007-05-04 13:41:52.000000000 +0800 @@ -216,6 +216,23 @@ } break; + case '"': + len++; + if (dst) + *dst++ = ch; + + while (*src && *src != '"') { + len++; + if (dst) + *dst++ = *src; + src++; + } + if (*src && dst) { + len++; + *dst++ = *src++; + } + break; + case ':': if (dst) *(dst++) = @@ -596,7 +613,10 @@ MODPREFIX "unexpected NULL map entry pointer"); return 0; } - + + if (*p == '"') + p++; + /* If first character is "/" it's a multi-mount */ if (*p == '/') return 1; @@ -613,6 +633,8 @@ * entry. */ if (not_first_chunk) { + if (*p == '"') + p++; if (*p == '/' || *p == '-') { multi = 1; break; @@ -772,13 +794,6 @@ debug(logopt, MODPREFIX "gathered options: %s", myoptions); - /* Location can't begin with a '/' */ - if (*p == '/') { - warn(logopt, MODPREFIX "error location begins with \"/\""); - free(myoptions); - return 0; - } - l = chunklen(p, check_colon(p)); loc = dequote(p, l, logopt); if (!loc) { @@ -787,6 +802,13 @@ return 0; } + /* Location can't begin with a '/' */ + if (*p == '/') { + warn(logopt, MODPREFIX "error location begins with \"/\""); + free(myoptions); + return 0; + } + if (!validate_location(loc)) { warn(logopt, MODPREFIX "invalid location"); free(myoptions); @@ -799,22 +821,22 @@ p += l; p = skipspace(p); - while (*p && *p != '/') { + while (*p && ((*p == '"' && *(p + 1) != '/') || (*p != '"' && *p != '/'))) { char *tmp, *ent; - /* Location can't begin with a '/' */ - if (*p == '/') { - warn(logopt, - MODPREFIX "error location begins with \"/\""); + l = chunklen(p, check_colon(p)); + ent = dequote(p, l, logopt); + if (!ent) { + warn(logopt, MODPREFIX "null location or out of memory"); free(myoptions); free(loc); return 0; } - l = chunklen(p, check_colon(p)); - ent = dequote(p, l, logopt); - if (!ent) { - warn(logopt, MODPREFIX "null location or out of memory"); + /* Location can't begin with a '/' */ + if (*p == '/') { + warn(logopt, + MODPREFIX "error location begins with \"/\""); free(myoptions); free(loc); return 0; @@ -1100,7 +1122,7 @@ char *path, *myoptions, *loc; int status; - if (*p != '/') { + if ((*p == '"' && *(p + 1) != '/') || (*p != '"' && *p != '/')) { l = 0; path = dequote("/", 1, ap->logopt); debug(ap->logopt, @@ -1162,7 +1184,7 @@ free(loc); free(path); free(myoptions); - } while (*p == '/'); + } while (*p == '/' || (*p == '"' && *(p + 1) == '/')); /* * We've got the ordered list of multi-mount entries so go @@ -1226,14 +1248,6 @@ int loclen; int l; - /* Location can't begin with a '/' */ - if (*p == '/') { - free(options); - warn(ap->logopt, - MODPREFIX "error location begins with \"/\""); - return 1; - } - l = chunklen(p, check_colon(p)); loc = dequote(p, l, ap->logopt); if (!loc) { @@ -1242,6 +1256,14 @@ return 1; } + /* Location can't begin with a '/' */ + if (*p == '/') { + free(options); + warn(ap->logopt, + MODPREFIX "error location begins with \"/\""); + return 1; + } + if (!validate_location(loc)) { free(loc); free(options); --- autofs-5.0.1/samples/auto.smb.consistent-dquote-handling 2006-09-01 13:29:50.000000000 +0800 +++ autofs-5.0.1/samples/auto.smb 2007-05-04 13:41:52.000000000 +0800 @@ -20,7 +20,16 @@ $SMBCLIENT -gNL $key 2>/dev/null| awk -v key="$key" -v opts="$opts" -F'|' -- ' BEGIN { ORS=""; first=1 } - /Disk/ { if (first) { print opts; first=0 }; sub(/ /, "\\ ", $2); print " \\\n\t /" $2, "://" key "/" $2 } + /Disk/ { + if (first) + print opts; first=0 + dir = $2 + loc = $2 + # Enclose mount dir and location in quotes + # Double quote "$" in location as it is special + gsub(/\$$/, "\\$", loc); + print " \\\n\t \"/" dir "\"", "\"://" key "/" loc "\"" + } END { if (!first) print "\n"; else exit 1 } ' --- autofs-5.0.1/lib/parse_subs.c.consistent-dquote-handling 2007-05-04 13:40:48.000000000 +0800 +++ autofs-5.0.1/lib/parse_subs.c 2007-05-04 13:41:52.000000000 +0800 @@ -89,6 +89,18 @@ quote = 1; continue; } + case '"': + if (quote) + break; + while (*str) { + str++; + n++; + if (*str == '"') + break; + if (*str == ':') + expect_colon = 0; + } + break; case ':': if (expect_colon) expect_colon = 0; @@ -197,11 +209,19 @@ const char *p = str; unsigned int len = 0; - while (!isblank(*(p++)) && len++ < maxlen) { - if (*p == '\\') { + while (*p && !isblank(*p) && len < maxlen) { + if (*p == '"') { + while (*p++ && len++ < maxlen) { + if (*p == '"') + break; + } + } else if (*p == '\\') { p += 2; len += 2; + continue; } + p++; + len++; } return len; }