diff options
author | roberto <roberto@FreeBSD.org> | 2002-05-23 13:16:30 +0000 |
---|---|---|
committer | roberto <roberto@FreeBSD.org> | 2002-05-23 13:16:30 +0000 |
commit | 9ace91bc729f7693cd7b4a139c15487acec69304 (patch) | |
tree | 3f81dae7ad6c88f45b1a7490dd01318fbab6544c /usr.sbin | |
parent | 59fca5c21df184b57c56627a032ac10084ab939c (diff) | |
download | FreeBSD-src-9ace91bc729f7693cd7b4a139c15487acec69304.zip FreeBSD-src-9ace91bc729f7693cd7b4a139c15487acec69304.tar.gz |
load_env(), the function that attempts to parse a crontab
line as an environment variable assignment, is broken
and not conformant to its description in the manual page.
I think it is worthwhile to have that fix in 4.6.
PR: bin/38374
Submitted by: Thomas Quinot <thomas@cuivre.fr.eu.org>
MFC after: 2 days
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/cron/lib/env.c | 99 |
1 files changed, 76 insertions, 23 deletions
diff --git a/usr.sbin/cron/lib/env.c b/usr.sbin/cron/lib/env.c index 1703735..c2adb49 100644 --- a/usr.sbin/cron/lib/env.c +++ b/usr.sbin/cron/lib/env.c @@ -145,7 +145,18 @@ load_env(envstr, f) long filepos; int fileline; char name[MAX_ENVSTR], val[MAX_ENVSTR]; - int fields; + char quotechar, *c, *str; + int state; + + /* The following states are traversed in order: */ +#define NAMEI 0 /* First char of NAME, may be quote */ +#define NAME 1 /* Subsequent chars of NAME */ +#define EQ1 2 /* After end of name, looking for '=' sign */ +#define EQ2 3 /* After '=', skipping whitespace */ +#define VALUEI 4 /* First char of VALUE, may be quote */ +#define VALUE 5 /* Subsequent chars of VALUE */ +#define FINI 6 /* All done, skipping trailing whitespace */ +#define ERROR 7 /* Error */ filepos = ftell(f); fileline = LineNumber; @@ -153,35 +164,77 @@ load_env(envstr, f) if (EOF == get_string(envstr, MAX_ENVSTR, f, "\n")) return (ERR); - Debug(DPARS, ("load_env, read <%s>\n", envstr)) + Debug(DPARS, ("load_env, read <%s>\n", envstr)); - name[0] = val[0] = '\0'; - fields = sscanf(envstr, "%[^ =] = %[^\n#]", name, val); - if (fields != 2) { - Debug(DPARS, ("load_env, not 2 fields (%d)\n", fields)) + bzero (name, sizeof name); + bzero (val, sizeof val); + str = name; + state = NAMEI; + quotechar = '\0'; + c = envstr; + while (state != ERROR && *c) { + switch (state) { + case NAMEI: + case VALUEI: + if (*c == '\'' || *c == '"') + quotechar = *c++; + ++state; + /* FALLTHROUGH */ + case NAME: + case VALUE: + if (quotechar) { + if (*c == quotechar) { + state++; + c++; + break; + } + if (state == NAME && *c == '=') { + state = ERROR; + break; + } + } else { + if (isspace (*c)) { + state++; + c++; + break; + } + if (state == NAME && *c == '=') { + state++; + break; + } + } + *str++ = *c++; + break; + + case EQ1: + if (*c == '=') { + state++; + str = val; + quotechar = '\0'; + } else { + if (!isspace (*c)) + state = ERROR; + } + c++; + break; + case EQ2: + case FINI: + if (isspace (*c)) + c++; + else + state++; + break; + } + } + if (state != FINI && !(state == VALUE && !quotechar)) { + Debug(DPARS, ("load_env, parse error, state = %d\n", state)) fseek(f, filepos, 0); Set_LineNum(fileline); return (FALSE); } - /* 2 fields from scanf; looks like an env setting - */ - - /* - * process value string + /* 2 fields from parser; looks like an env setting */ - /*local*/{ - int len = strdtb(val); - - if (len >= 2) { - if (val[0] == '\'' || val[0] == '"') { - if (val[len-1] == val[0]) { - val[len-1] = '\0'; - (void) strcpy(val, val+1); - } - } - } - } if (strlen(name) + 1 + strlen(val) >= MAX_ENVSTR-1) return (FALSE); |