aboutsummaryrefslogtreecommitdiffstats
path: root/alsause.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--alsause.c330
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;
-}