return 0;
}
-/*****************************************************************************
- * FindEndCommand
- *****************************************************************************/
-static const char *FindEndCommand( const char *psz_sent )
+/**
+ * FindCommandEnd: look for the end of a possibly quoted string
+ * @return NULL on mal-formatted string,
+ * pointer paste the last character otherwise.
+ */
+static const char *FindCommandEnd (const char *psz_sent)
{
- vlc_bool_t b_escape = VLC_FALSE;
+ char quote = psz_sent[0], c;
+ static const char quotes[] = "'\"";
+
+ if (quote && (strchr (quotes, quote) == NULL))
+ quote = '\0';
- switch( *psz_sent )
+ while ((c = *psz_sent) != '\0')
{
- case '\"':
- psz_sent++;
- while( ( *psz_sent != '\"' || b_escape == VLC_TRUE )
- && ( *psz_sent != '\0' ) )
+ if (c == '\\')
{
- if( *psz_sent == '\'' && b_escape == VLC_FALSE )
- {
- psz_sent = FindEndCommand( psz_sent );
- if( psz_sent == NULL ) return NULL;
- }
- else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
- b_escape = VLC_TRUE;
- else
- b_escape = VLC_FALSE;
- }
+ if (*psz_sent == '\0')
+ return NULL; // cannot escape "nothing"
- if( *psz_sent == '\"' )
- {
- psz_sent++;
- return psz_sent;
+ psz_sent++; // skips escaped character
}
+ else
+ if (c == quote) // non-escaped matching quote
+ return psz_sent + 1;
+ else
+ if (isblank (c)) // non-escaped blank
+ return psz_sent;
- /* *psz_sent == '\0' -> number of " is incorrect */
- else return NULL;
-
- break;
-
- case '\'':
psz_sent++;
- while( ( *psz_sent != '\'' || b_escape == VLC_TRUE )
- && ( *psz_sent != '\0' ) )
- {
- if( *psz_sent == '\"' && b_escape == VLC_FALSE )
- {
- psz_sent = FindEndCommand( psz_sent );
- if( psz_sent == NULL ) return NULL;
- }
- else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
- b_escape = VLC_TRUE;
- else
- b_escape = VLC_FALSE;
- }
+ }
- if( *psz_sent == '\'' )
- {
- psz_sent++;
- return psz_sent;
- }
+ // error (NULL) if we could not find a matching quote
+ return quote ? NULL : psz_sent;
+}
- /* *psz_sent == '\0' -> number of " is incorrect */
- else return NULL;
- break;
+/**
+ * Unescape (C-style) a nul-terminated string.
+ * Note that in and out can be identical.
+ *
+ * @param out output buffer (at least <strlen (in) + 1> characters long)
+ * @param in nul-terminated string to be unescaped
+ *
+ * @return 0 on success, -1 on error.
+ */
+static int Unescape (char *out, const char *in)
+{
+ char c;
- default: /* now we can look for spaces */
- while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
+ while ((c = *in++) != '\0')
+ {
+ if (c == '\\')
{
- if( ( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
- && b_escape == VLC_FALSE )
+ switch (c = *in++)
{
- psz_sent = FindEndCommand( psz_sent );
- if( psz_sent == NULL ) return NULL;
+ case 'n':
+ *out++ = '\n';
+ continue;
+
+ case 't':
+ *out++ = '\t';
+ continue;
+
+ case 'r':
+ *out++ = '\r';
+ continue;
}
- else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
- b_escape = VLC_TRUE;
- else
- b_escape = VLC_FALSE;
+ // Only allow printable ASCII characters
+ // (in particular, no nul and no extended characters)
+ if (c < 32)
+ return -1;
}
-
- return psz_sent;
+ *out++ = c;
}
+
+ *out = '\0';
+ return 0;
}
+
/*****************************************************************************
* ExecuteCommand: The main state machine
*****************************************************************************
/* First, parse the line and cut it */
while( *psz_cmd != '\0' )
{
-
if( *psz_cmd == ' ' || *psz_cmd == '\t' )
{
psz_cmd++;
else
{
const char *psz_temp;
- const char *psz_buf;
- char *psz_dst;
- vlc_bool_t b_escape = VLC_FALSE;
- int i_temp;
/* support for comments */
if( i_command == 0 && *psz_cmd == '#')
goto success;
}
- psz_temp = FindEndCommand( psz_cmd );
+ psz_temp = FindCommandEnd( psz_cmd );
if( psz_temp == NULL )
{
goto error;
}
- i_temp = psz_temp - psz_cmd;
-
ppsz_command = realloc( ppsz_command, (i_command + 1) *
sizeof(char*) );
- ppsz_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
+ ppsz_command[i_command] = strndup (psz_cmd, psz_temp - psz_cmd);
/* unescape ", ' and \ ... and everything else */
- psz_buf = psz_cmd;
- psz_dst = ppsz_command[ i_command ];
- while( i_temp-- )
- {
- if( *psz_buf == '\\' && b_escape == VLC_FALSE )
- b_escape = VLC_TRUE;
- else
- {
- b_escape = VLC_FALSE;
- *psz_dst = *psz_buf;
- psz_dst++;
- }
- psz_buf++;
- }
- *psz_dst = '\0';
+ Unescape (ppsz_command[i_command], ppsz_command[i_command]);
i_command++;
-
psz_cmd = psz_temp;
}
}