From: Takashi Iwai Date: Fri, 10 Aug 2012 12:14:28 +0000 (+0200) Subject: ucm: Improve cset command parsing X-Git-Tag: android-x86-9.0-r1~942 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=58d10c09e12fde9c24650dfb798b7700e1431a65;p=android-x86%2Fexternal-alsa-lib.git 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 Signed-off-by: Takashi Iwai --- 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 #include #include @@ -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)