* [PATCH] ucm: Allow cset commands to have values with spaces. @ 2012-08-09 13:43 Tanu Kaskinen 2012-08-09 14:07 ` Takashi Iwai 2012-08-09 15:16 ` [PATCH v2] " Tanu Kaskinen 0 siblings, 2 replies; 6+ messages in thread From: Tanu Kaskinen @ 2012-08-09 13:43 UTC (permalink / raw) To: alsa-devel; +Cc: Takashi Iwai, Tanu Kaskinen An example: cset "name='Input Select' Digital Mic" The old parsing code interpreted "name='Input Select' Digital" as the element id, which of course didn't work. Signed-off-by: Tanu Kaskinen <tanu.kaskinen@digia.com> --- src/ucm/main.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ucm/main.c b/src/ucm/main.c index 4b37776..05a7b0a 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -170,8 +170,23 @@ 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) { + /* Find the space after the element id, taking quoting with + single-quotes into account. */ + for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) { + if (*pos == ' ') + break; + if (*pos == '\'') { + pos++; + pos += strcspn(pos, "'"); + if (*pos == '\0') { + uc_error("invalid element id (closing single-quote not found): %s", cset); + err = -EINVAL; + goto __fail; + } + pos++; + } + } + if (*pos == '\0') { uc_error("undefined value for cset >%s<", cset); err = -EINVAL; goto __fail; -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] ucm: Allow cset commands to have values with spaces. 2012-08-09 13:43 [PATCH] ucm: Allow cset commands to have values with spaces Tanu Kaskinen @ 2012-08-09 14:07 ` Takashi Iwai 2012-08-09 14:44 ` Kaskinen Tanu 2012-08-09 15:16 ` [PATCH v2] " Tanu Kaskinen 1 sibling, 1 reply; 6+ messages in thread From: Takashi Iwai @ 2012-08-09 14:07 UTC (permalink / raw) To: Tanu Kaskinen; +Cc: alsa-devel At Thu, 9 Aug 2012 16:43:31 +0300, Tanu Kaskinen wrote: > > An example: > cset "name='Input Select' Digital Mic" > > The old parsing code interpreted "name='Input Select' Digital" > as the element id, which of course didn't work. > > Signed-off-by: Tanu Kaskinen <tanu.kaskinen@digia.com> > --- > src/ucm/main.c | 19 +++++++++++++++++-- > 1 file changed, 17 insertions(+), 2 deletions(-) > > diff --git a/src/ucm/main.c b/src/ucm/main.c > index 4b37776..05a7b0a 100644 > --- a/src/ucm/main.c > +++ b/src/ucm/main.c > @@ -170,8 +170,23 @@ 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) { > + /* Find the space after the element id, taking quoting with > + single-quotes into account. */ > + for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) { > + if (*pos == ' ') > + break; > + if (*pos == '\'') { A double-quote can be supported easily here... Takashi > + pos++; > + pos += strcspn(pos, "'"); > + if (*pos == '\0') { > + uc_error("invalid element id (closing single-quote not found): %s", cset); > + err = -EINVAL; > + goto __fail; > + } > + pos++; > + } > + } > + if (*pos == '\0') { > uc_error("undefined value for cset >%s<", cset); > err = -EINVAL; > goto __fail; > -- > 1.7.9.5 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ucm: Allow cset commands to have values with spaces. 2012-08-09 14:07 ` Takashi Iwai @ 2012-08-09 14:44 ` Kaskinen Tanu 2012-08-09 15:12 ` Takashi Iwai 0 siblings, 1 reply; 6+ messages in thread From: Kaskinen Tanu @ 2012-08-09 14:44 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote: > At Thu, 9 Aug 2012 16:43:31 +0300, > Tanu Kaskinen wrote: > > @@ -170,8 +170,23 @@ 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) { > > + /* Find the space after the element id, taking quoting with > > + single-quotes into account. */ > > + for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) { > > + if (*pos == ' ') > > + break; > > + if (*pos == '\'') { > > A double-quote can be supported easily here... True, I'll post v2 soon. -- Tanu ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ucm: Allow cset commands to have values with spaces. 2012-08-09 14:44 ` Kaskinen Tanu @ 2012-08-09 15:12 ` Takashi Iwai 2012-08-09 15:23 ` Kaskinen Tanu 0 siblings, 1 reply; 6+ messages in thread From: Takashi Iwai @ 2012-08-09 15:12 UTC (permalink / raw) To: Kaskinen Tanu; +Cc: alsa-devel At Thu, 9 Aug 2012 17:44:12 +0300, Kaskinen Tanu wrote: > > On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote: > > At Thu, 9 Aug 2012 16:43:31 +0300, > > Tanu Kaskinen wrote: > > > @@ -170,8 +170,23 @@ 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) { > > > + /* Find the space after the element id, taking quoting with > > > + single-quotes into account. */ > > > + for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) { > > > + if (*pos == ' ') > > > + break; > > > + if (*pos == '\'') { > > > > A double-quote can be supported easily here... > > True, I'll post v2 soon. On the second thought, parsing the string intensively at that point doesn't make sense. The string will be parsed anyway in snd_ctl_ascii_elem_id_parse(), then why not just let it give the next pointer from there? Below is a quick hack (untested at all!). Could you check whether it works? Takashi --- diff --git a/src/control/ctlparse.c b/src/control/ctlparse.c index a16f96a..b0c4ef3 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 4b37776..bd5c348 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) ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] ucm: Allow cset commands to have values with spaces. 2012-08-09 15:12 ` Takashi Iwai @ 2012-08-09 15:23 ` Kaskinen Tanu 0 siblings, 0 replies; 6+ messages in thread From: Kaskinen Tanu @ 2012-08-09 15:23 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel On Thu, 2012-08-09 at 17:12 +0200, Takashi Iwai wrote: > At Thu, 9 Aug 2012 17:44:12 +0300, > Kaskinen Tanu wrote: > > > > On Thu, 2012-08-09 at 16:07 +0200, Takashi Iwai wrote: > > > At Thu, 9 Aug 2012 16:43:31 +0300, > > > Tanu Kaskinen wrote: > > > > @@ -170,8 +170,23 @@ 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) { > > > > + /* Find the space after the element id, taking quoting with > > > > + single-quotes into account. */ > > > > + for (pos = cset; *pos != '\0'; pos += strcspn(pos, "' ")) { > > > > + if (*pos == ' ') > > > > + break; > > > > + if (*pos == '\'') { > > > > > > A double-quote can be supported easily here... > > > > True, I'll post v2 soon. > > On the second thought, parsing the string intensively at that point > doesn't make sense. The string will be parsed anyway in > snd_ctl_ascii_elem_id_parse(), then why not just let it give the next > pointer from there? > > Below is a quick hack (untested at all!). Could you check whether it > works? It does :) -- Tanu ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] ucm: Allow cset commands to have values with spaces. 2012-08-09 13:43 [PATCH] ucm: Allow cset commands to have values with spaces Tanu Kaskinen 2012-08-09 14:07 ` Takashi Iwai @ 2012-08-09 15:16 ` Tanu Kaskinen 1 sibling, 0 replies; 6+ messages in thread From: Tanu Kaskinen @ 2012-08-09 15:16 UTC (permalink / raw) To: alsa-devel; +Cc: Takashi Iwai, Tanu Kaskinen An example: cset "name='Input Select' Digital Mic" The old parsing code interpreted "name='Input Select' Digital" as the element id, which of course didn't work. Signed-off-by: Tanu Kaskinen <tanu.kaskinen@digia.com> --- src/ucm/main.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/ucm/main.c b/src/ucm/main.c index 4b37776..518349a 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -162,6 +162,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset) { char *pos; int err; + int nulled = 0; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *value; snd_ctl_elem_info_t *info; @@ -170,13 +171,28 @@ 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) { + /* Find the space after the element id, taking quoting into account. */ + for (pos = cset; *pos != ' ' && *pos != '\0'; pos += strcspn(pos, " '\"")) { + if (*pos == '\'' || *pos == '"') { + char quote = *pos; + + pos++; + pos = strchr(pos, quote); + if (pos == NULL) { + uc_error("invalid element id (closing quote not found): %s", cset); + err = -EINVAL; + goto __fail; + } + pos++; + } + } + if (*pos == '\0') { uc_error("undefined value for cset >%s<", cset); err = -EINVAL; goto __fail; } *pos = '\0'; + nulled = 1; err = snd_ctl_ascii_elem_id_parse(id, cset); if (err < 0) goto __fail; @@ -196,7 +212,7 @@ static int execute_cset(snd_ctl_t *ctl, char *cset) goto __fail; err = 0; __fail: - if (pos != NULL) + if (nulled) *pos = ' '; if (id != NULL) -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-08-09 14:53 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-08-09 13:43 [PATCH] ucm: Allow cset commands to have values with spaces Tanu Kaskinen 2012-08-09 14:07 ` Takashi Iwai 2012-08-09 14:44 ` Kaskinen Tanu 2012-08-09 15:12 ` Takashi Iwai 2012-08-09 15:23 ` Kaskinen Tanu 2012-08-09 15:16 ` [PATCH v2] " Tanu Kaskinen
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.