diff options
Diffstat (limited to '')
| -rw-r--r-- | alsause.c | 330 |
1 files changed, 0 insertions, 330 deletions
diff --git a/alsause.c b/alsause.c deleted file mode 100644 index 5cb923d..0000000 --- a/alsause.c +++ /dev/null @@ -1,330 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <sys/mount.h> -#ifndef OPEN_TREE_CLONE -# define MISSING_OPEN_TREE -#endif -#ifndef MOVE_MOUNT_F_EMPTY_PATH -# define MISSING_MOVE_MOUNT -#endif -#if defined(MISSING_OPEN_TREE) || defined(MISSING_MOVE_MOUNT) -# include <linux/mount.h> -# include <sys/syscall.h> -#endif -#include <sched.h> -#include <alsa/asoundlib.h> -#include <libsimple.h> -#include <libsimple-arg.h> - -NUSAGE(125, "[(-r | name | card:device) [command [argument] ...]]"); - - -#ifdef MISSING_OPEN_TREE -static int -open_tree(int dirfd, const char *path, int flags) -{ - return syscall(SYS_open_tree, dirfd, path, flags); -} -#endif - - -#ifdef MISSING_MOVE_MOUNT -static int -move_mount(int dirfd1, const char *path1, int dirfd2, const char *path2, int flags) -{ - return syscall(SYS_move_mount, dirfd1, path1, dirfd2, path2, flags); -} -#endif - - -static char * -get_config_path(void) -{ - const char *home = getenv("HOME"); - char *ret; - if (!home) { - struct passwd *pw; - errno = 0; - pw = getpwuid(getuid()); - if (!pw || !pw->pw_dir) - eprintf("pwgetuid <real user>: %s", (!errno || errno == EIO) ? "User does not exist" : strerror(errno)); - home = pw->pw_dir; - } - if (strlen(home) > SIZE_MAX - sizeof("/.asoundrc") || - !(ret = malloc(strlen(home) + sizeof("/.asoundrc")))) { - errno = ENOMEM; - eprintf("malloc:"); - } - stpcpy(stpcpy(ret, home), "/.asoundrc"); - return ret; -} - - -#if defined(__GNUC__) -__attribute__((__pure__)) -#endif -static int -is_name(const char *s) -{ - if (!isdigit(*s)) - return 1; - if (*s == '0' && s[1] != ':') - return 1; - while (isdigit(*s)) - s++; - if (*s != ':') - return 1; - s++; - - if (!isdigit(*s)) - return 1; - if (*s == '0' && s[1]) - return 1; - while (isdigit(*s)) - s++; - if (*s) - return 1; - return 0; -} - - -static int -list_outputs(const char *find, int *card_out, int *device_out) -{ - snd_ctl_t *ctl; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - char dev[sizeof("hw:") + 3 * sizeof(int)]; - int r, card, device, failed = 0; - - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - - for (card = -1;;) { - r = snd_card_next(&card); - if (r < 0) { - weprintf("snd_card_next: %s", snd_strerror(r)); - return -1; - } - if (card < 0) - break; - - sprintf(dev, "hw:%i", card); - r = snd_ctl_open(&ctl, dev, 0); - if (r < 0) { - weprintf("snd_ctl_open %s 0: %s", dev, snd_strerror(r)); - failed = 1; - continue; - } - - r = snd_ctl_card_info(ctl, info); - if (r < 0) { - weprintf("snd_ctl_card_info <%s>: %s", dev, snd_strerror(r)); - failed = 1; - goto close_card; - } - - for (device = -1;;) { - r = snd_ctl_pcm_next_device(ctl, &device); - if (r < 0) { - weprintf("snd_ctl_pcm_next_device <%s>: %s", dev, snd_strerror(r)); - failed = 1; - goto close_card; - } - if (device < 0) - break; - - snd_pcm_info_set_device(pcminfo, (unsigned int)device); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); - r = snd_ctl_pcm_info(ctl, pcminfo); - if (r < 0) { - if (r == -ENOENT) - continue; - weprintf("snd_ctl_pcm_info <%s>: %s (%i)", dev, snd_strerror(r), r); - failed = 1; - goto close_card; - } - - if (find) { - const char *s, *n = find; - s = snd_ctl_card_info_get_name(info); - if (strncmp(n, s, strlen(s))) - continue; - n = &n[strlen(s)]; - if (strncmp(n, " - ", 3)) - continue; - n = &n[3]; - s = snd_pcm_info_get_name(pcminfo); - if (strcmp(n, s)) - continue; - *card_out = snd_ctl_card_info_get_card(info); - *device_out = device; - snd_ctl_close(ctl); - return 0; - } else { - printf("%i:%i\t%s - %s\n", - snd_ctl_card_info_get_card(info), device, - snd_ctl_card_info_get_name(info), - snd_pcm_info_get_name(pcminfo)); - } - } - - close_card: - snd_ctl_close(ctl); - } - - if (find) { - *card_out = -1; - *device_out = -1; - } - return -failed; -} - - -static int -writeall(int fd, void *data, size_t len) -{ - char *text = data; - ssize_t r; - while (len) { - r = write(fd, text, len); - if (r < 0) { - if (errno == EINTR) - continue; - return -1; - } - text = &text[r]; - len -= (size_t)r; - } - return 0; -} - - -int -main(int argc, char *argv[]) -{ - int reset = 0; - - libsimple_default_failure_exit = 125; - - ARGBEGIN { - case 'r': - reset = 1; - break; - default: - usage(); - } ARGEND; - - if (!argc) { - if (reset) { - char *path = get_config_path(); - if (unlink(path) && errno != ENOENT) - eprintf("unlink %s:", path); - free(path); - } else { - if (list_outputs(NULL, NULL, NULL)) - return libsimple_default_failure_exit; - } - } else { - char *path = get_config_path(); - char *text, temppath[sizeof("/tmp/alsause.") + 3 * sizeof(uintmax_t)]; - int len, fd, treefd; - if (reset) { - text = NULL; - len = 0; - } else if (is_name(argv[0])) { - int card, device; - if (list_outputs(argv[0], &card, &device)) - return 1; - if (card == -1 || device == -1) - eprintf("audio output \"%s\" not found", argv[0]); - len = snprintf(NULL, 0, "defaults.pcm.card %i\ndefaults.pcm.device %i\n", card, device); - if (len < 0) - eprintf("snprintf NULL 0:"); - text = malloc((size_t)len + 1U); - if (!text) - eprintf("malloc:"); - if (sprintf(text, "defaults.pcm.card %i\ndefaults.pcm.device %i\n", card, device) != len) - abort(); - argc--; - argv++; - } else { - char *card = argv[0]; - char *device = strchr(card, ':'); - if (!device) - usage(); - *device++ = '\0'; - if (strchr(device, ':')) - usage(); - len = snprintf(NULL, 0, "defaults.pcm.card %s\ndefaults.pcm.device %s\n", card, device); - if (len < 0) - eprintf("snprintf NULL 0:"); - text = malloc((size_t)len + 1U); - if (!text) - eprintf("malloc:"); - if (sprintf(text, "defaults.pcm.card %s\ndefaults.pcm.device %s\n", card, device) != len) - abort(); - argc--; - argv++; - } - - if (!argc) { - fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0666); - if (fd < 0) - eprintf("open %s O_CREAT|O_TRUNC|O_WRONLY 0666:", path); - if (fchown(fd, getuid(), getgid())) - weprintf("fchown %s <read user> <real path>:", path); - if (writeall(fd, text, (size_t)len) || (close(fd) && (errno != EINTR))) - eprintf("write %s:", path); - free(text); - free(path); - return 0; - } - - if (unshare(CLONE_NEWNS)) - eprintf("unshare CLONE_NEWNS:"); - if (mount("none", "/", NULL, MS_REC | MS_SLAVE, NULL)) - eprintf("mount none / NULL MS_REC|MS_SLAVE NULL:"); - - fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0666); - if (fd >= 0) { - fchown(fd, getuid(), getgid()); - close(fd); - } - - sprintf(temppath, "/tmp/alsause.%ju", (uintmax_t)getpid()); - unlink(temppath); - fd = open(temppath, O_CREAT | O_EXCL | O_WRONLY, 0666); - if (fd < 0) - eprintf("open %s O_CREAT|O_EXCL|O_WRONLY 0666:", temppath); - if (fchown(fd, getuid(), getgid())) - weprintf("fchown %s <read user> <real path>:", temppath); - if (writeall(fd, text, (size_t)len) || (close(fd) && (errno != EINTR))) - eprintf("write %s:", temppath); - free(text); - - treefd = open_tree(AT_FDCWD, temppath, OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC); - if (treefd < 0) { - weprintf("open_tree AT_FDCWD %s OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC:", temppath); - unlink(temppath); - exit(libsimple_default_failure_exit); - } - if (move_mount(treefd, "", AT_FDCWD, path, MOVE_MOUNT_F_EMPTY_PATH)) { - weprintf("move_mount %s \"\" AT_FDCWD %s MOVE_MOUNT_F_EMPTY_PATH:", temppath, path); - unlink(temppath); - exit(libsimple_default_failure_exit); - } - - if (unlink(temppath)) - weprintf("unlink %s:", temppath); - if (setegid(getgid())) - eprintf("setegid <real group>:"); - if (seteuid(getuid())) - eprintf("seteuid <real user>:"); - - execvp(argv[0], argv); - enprintf(errno == ENOENT ? 127 : 126, "execvp %s:", argv[0]); - } - - return 0; -} |
