summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-08-10 14:14:28 +0200
committerTakashi Iwai <tiwai@suse.de>2012-08-10 14:14:28 +0200
commit58d10c09e12fde9c24650dfb798b7700e1431a65 (patch)
treea02e89dfa457d003b191826cc34e933fd6b0e4db
parentc34f74c818c6ced0aa8e8b7002ba37b14c5de71b (diff)
downloadalsa-lib-58d10c09e12fde9c24650dfb798b7700e1431a65.tar.gz
ucm: Improve cset command parsing
The cset command parsing in ucm/main.c assumes implicitly that the argument contains no space, thus an example below wouldn't work: cset "name='Input Select' Digital Mic" This patch introduces a new internal API function __snd_ctl_ascii_elem_id_parse() to improve the cset parser. Reported-by: Tanu Kaskinen <tanu.kaskinen@digia.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--src/control/ctlparse.c46
-rw-r--r--src/ucm/main.c24
2 files changed, 46 insertions, 24 deletions
diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c
index a16f96a9..b0c4ef37 100644
--- a/src/control/ctlparse.c
+++ b/src/control/ctlparse.c
@@ -143,21 +143,19 @@ char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id)
return strdup(buf);
}
-/**
- * \brief parse ASCII string as CTL element identifier
- * \param dst destination CTL identifier
- * \param str source ASCII string
- * \return zero on success, otherwise a negative error code
- */
-int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
+#ifndef DOC_HIDDEN
+/* used by UCM parser, too */
+int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str,
+ const char **ret_ptr)
{
int c, size, numid;
+ int err = -EINVAL;
char *ptr;
- while (*str == ' ' || *str == '\t')
+ while (isspace(*str))
str++;
if (!(*str))
- return -EINVAL;
+ goto out;
snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_MIXER); /* default */
while (*str) {
if (!strncasecmp(str, "numid=", 6)) {
@@ -165,7 +163,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
numid = atoi(str);
if (numid <= 0) {
fprintf(stderr, "amixer: Invalid numid %d\n", numid);
- return -EINVAL;
+ goto out;
}
snd_ctl_elem_id_set_numid(dst, atoi(str));
while (isdigit(*str))
@@ -191,7 +189,7 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
snd_ctl_elem_id_set_interface(dst, SND_CTL_ELEM_IFACE_SEQUENCER);
str += 9;
} else {
- return -EINVAL;
+ goto out;
}
} else if (!strncasecmp(str, "name=", 5)) {
char buf[64];
@@ -239,11 +237,33 @@ int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
if (*str == ',') {
str++;
} else {
+ /* when ret_ptr is given, allow to terminate gracefully
+ * at the next space letter
+ */
+ if (ret_ptr && isspace(*str))
+ break;
if (*str)
- return -EINVAL;
+ goto out;
}
}
- return 0;
+ err = 0;
+
+ out:
+ if (ret_ptr)
+ *ret_ptr = str;
+ return err;
+}
+#endif
+
+/**
+ * \brief parse ASCII string as CTL element identifier
+ * \param dst destination CTL identifier
+ * \param str source ASCII string
+ * \return zero on success, otherwise a negative error code
+ */
+int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str)
+{
+ return __snd_ctl_ascii_elem_id_parse(dst, str, NULL);
}
static int get_ctl_enum_item_index(snd_ctl_t *handle,
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 4b377764..bd5c3481 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -31,6 +31,7 @@
*/
#include "ucm_local.h"
+#include <ctype.h>
#include <stdarg.h>
#include <pthread.h>
@@ -158,9 +159,13 @@ static int open_ctl(snd_use_case_mgr_t *uc_mgr,
return 0;
}
+extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst,
+ const char *str,
+ const char **ret_ptr);
+
static int execute_cset(snd_ctl_t *ctl, char *cset)
{
- char *pos;
+ const char *pos;
int err;
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *value;
@@ -170,16 +175,16 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
snd_ctl_elem_value_malloc(&value);
snd_ctl_elem_info_malloc(&info);
- pos = strrchr(cset, ' ');
- if (pos == NULL) {
+ err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos);
+ if (err < 0)
+ goto __fail;
+ while (*pos && isspace(*pos))
+ pos++;
+ if (!*pos) {
uc_error("undefined value for cset >%s<", cset);
err = -EINVAL;
goto __fail;
}
- *pos = '\0';
- err = snd_ctl_ascii_elem_id_parse(id, cset);
- if (err < 0)
- goto __fail;
snd_ctl_elem_value_set_id(value, id);
snd_ctl_elem_info_set_id(info, id);
err = snd_ctl_elem_read(ctl, value);
@@ -188,7 +193,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
err = snd_ctl_elem_info(ctl, info);
if (err < 0)
goto __fail;
- err = snd_ctl_ascii_value_parse(ctl, value, info, pos + 1);
+ err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
if (err < 0)
goto __fail;
err = snd_ctl_elem_write(ctl, value);
@@ -196,9 +201,6 @@ static int execute_cset(snd_ctl_t *ctl, char *cset)
goto __fail;
err = 0;
__fail:
- if (pos != NULL)
- *pos = ' ';
-
if (id != NULL)
free(id);
if (value != NULL)