diff --git a/envy24control/envy24control.c b/envy24control/envy24control.c index 0b2749e..3798ba3 100644 --- a/envy24control/envy24control.c +++ b/envy24control/envy24control.c @@ -2084,24 +2166,50 @@ int main(int argc, char **argv) view_spdif_playback = 0; profiles_file_name = DEFAULT_PROFILERC; default_profile = NULL; while ((c = getopt_long(argc, argv, "D:c:f:i:m:Mo:p:s:w:vt:", long_options, NULL)) != -1) { switch (c) { case 'D': - name = optarg; - card_number = atoi(strchr(name, ':') + sizeof(char)); - if (card_number < 0 || card_number >= MAX_CARD_NUMBERS) { - fprintf(stderr, "envy24control: invalid card number %d\n", card_number); - exit(1); - } + /* + * NPM: use ALSA code to fix/validate + * https://bugzilla.redhat.com/show_bug.cgi?id=602900 + * The old code assumed ':' present, e.g. "-Dhw:66", (w/ + * .asoundrc "ctl.66 {type hw, card M66}") and would + * coredump if given "-D66". Here, by not worrying about + * "hw:" and passing "optarg" as-is via 'name' to + * snd_ctl_open() below, resolves the issue, giving similar + * behavior as 'amixer'. However, letting snd_ctl_open() + * validate gives less helpful error messages on + * failure: "envy24control -Dhw:foo" + * ==> "snd_ctl_open: No such device" + * So validate the arg as ALSA CTL, providing + * a more specific error message and fail first if not valid. + */ + name = optarg; /* NPM: e.g. pass "-D66" unaltered to snd_ctl_open() and let it validate valid ALSA CTL name */ + if (index(optarg, ':')) { /* NPM: handle e.g. optarg == "hw:M66" */ + card_number = snd_card_get_index(strchr(optarg, ':') + sizeof(char)); + if (card_number < 0) { + fprintf(stderr, "envy24control: invalid ALSA audio device, invalid index or name for card: %s\n", optarg); + exit(1); + } + } break; case 'c': - i = atoi(optarg); - if (i < 0 || i >= MAX_CARD_NUMBERS) { - fprintf(stderr, "envy24control: invalid card number %d\n", i); + /* + NPM: use snd_card_get_index() to fix/validate + https://bugzilla.redhat.com/show_bug.cgi?id=602900 + * NPM: nb :"The accepted format is + * an integer value in ASCII representation or the card + * identifier (the id parameter for sound-card + * drivers). The control device name like + * /dev/snd/controlC0 is accepted, too." + */ + card_number = snd_card_get_index(optarg); + if (card_number < 0) { /* NPM: code orig from alsa-utils/alsamixer/cli.c */ + fprintf(stderr, "envy24control: invalid ALSA index or name for audio card: %s\n", optarg); exit(1); } - card_number = i; - sprintf(tmpname, "hw:%d", i); + sprintf(tmpname, "hw:%d", card_number); /* e.g. "hw:M66" for arg "-cM66" passed to snd_ctl_open() below */ name = tmpname; break; case 'f':