Skip to content

Commit d561a8b

Browse files
committed
Refactor: remoted: Clean up load_env_vars()
The changes in this commit involve using (gchar *) strings and some dynamic allocation to make load_env_vars() easier to reason about. Previously, we tried to be as efficient as possible by reading a line into a buffer, iterating over it with multiple pointers, dividing it into name and value by insertion of a null terminator, etc. This is premature optimization. This function is not called along a path of execution where performance is so critical as to require this. In my opinion, clarity is more important. * Use pcmk__scan_nvpair() to separate the line on the equal sign. * Simplify name validation since we now have name as a separate string (before the equal sign) and don't need to return first and last pointers. * Skip the leading quote by converting it to a space and calling g_strchug() to memmove() value up by one position. This ensures that value still points to the beginning of the buffer, which simplifies freeing it later. Signed-off-by: Reid Wahl <[email protected]>
1 parent fe1d271 commit d561a8b

File tree

1 file changed

+33
-34
lines changed

1 file changed

+33
-34
lines changed

daemons/execd/remoted_pidone.c

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,26 @@ static struct {
6161

6262
/*!
6363
* \internal
64-
* \brief Check a line of text for a valid environment variable name
64+
* \brief Check whether a string is a valid environment variable name
6565
*
66-
* \param[in] line Text to check
66+
* \param[in] name String to check
6767
*
68-
* \return Last character of valid name if found, or \c NULL otherwise
68+
* \return \c true if \p name is a valid name, or \c false otherwise
6969
* \note It's reasonable to impose limitations on environment variable names
7070
* beyond what C or setenv() does: We only allow names that contain only
7171
* [a-zA-Z0-9_] characters and do not start with a digit.
7272
*/
73-
static char *
74-
find_env_var_name(char *line)
73+
static bool
74+
valid_env_var_name(const gchar *name)
7575
{
76-
if (!isalpha(*line) && (*line != '_')) {
76+
if (!isalpha(*name) && (*name != '_')) {
7777
// Invalid first character
78-
return NULL;
78+
return false;
7979
}
80-
for (line++; isalnum(*line) || (*line == '_'); line++);
81-
return line;
80+
81+
// The rest of the characters must be alphanumeric or underscores
82+
for (name++; isalnum(*name) || (*name == '_'); name++);
83+
return *name == '\0';
8284
}
8385

8486
#define CONTAINER_ENV_FILE "/etc/pacemaker/pcmk-init.env"
@@ -98,53 +100,48 @@ load_env_vars(void)
98100
}
99101

100102
while (getline(&line, &buf_size, fp) != -1) {
101-
char *name = NULL;
102-
char *end = NULL;
103-
char *value = NULL;
104-
char *comment = NULL;
103+
gchar *name = NULL;
104+
gchar *value = NULL;
105+
gchar *end = NULL;
106+
gchar *comment = NULL;
105107

106108
// Strip leading and trailing whitespace
107109
g_strstrip(line);
108110

109-
// Look for valid name immediately followed by equals sign
110-
end = find_env_var_name(line);
111-
if (*++end != '=') {
111+
if ((pcmk__scan_nvpair(line, &name, &value) != pcmk_rc_ok)
112+
|| !valid_env_var_name(name)) {
112113
goto cleanup_loop;
113114
}
114-
name = line;
115-
116-
// Null-terminate name, and advance beyond equals sign
117-
*end++ = '\0';
118115

119-
value = end;
120-
121-
// Check whether value is quoted
122116
if ((*value == '\'') || (*value == '"')) {
123-
const char *quote = *value++;
117+
char quote = *value;
118+
119+
// Strip the leading quote
120+
*value = ' ';
121+
g_strchug(value);
124122

125123
/* Value is remaining characters up to next non-backslashed matching
126124
* quote character.
127125
*/
128-
end = value;
129-
while (((*end != *quote) || (*(end - 1) == '\\'))
130-
&& (*end != '\0')) {
131-
end++;
132-
}
133-
if (*end != *quote) {
126+
for (end = value;
127+
(*end != '\0') && ((*end != quote) || (*(end - 1) == '\\'));
128+
end++);
129+
130+
if (*end != quote) {
134131
// Matching closing quote wasn't found
135132
goto cleanup_loop;
136133
}
134+
137135
// Discard closing quote and advance to check for trailing garbage
138136
*end++ = '\0';
139137

140138
} else {
141139
/* Value is remaining characters up to next non-backslashed
142140
* whitespace.
143141
*/
144-
while ((!isspace(*end) || (*(end - 1) == '\\'))
145-
&& (*end != '\0')) {
146-
end++;
147-
}
142+
for (end = value;
143+
(*end != '\0') && (!isspace(*end) || (*(end - 1) == '\\'));
144+
end++);
148145
}
149146

150147
/* We have a valid name and value, and end is now the character after
@@ -171,6 +168,8 @@ load_env_vars(void)
171168
setenv(name, value, 0);
172169

173170
cleanup_loop:
171+
g_free(name);
172+
g_free(value);
174173
errno = 0;
175174
}
176175

0 commit comments

Comments
 (0)