diff --git a/libsndio/amsg.h b/libsndio/amsg.h index 0b3c2e9..fa276a5 100644 --- a/libsndio/amsg.h +++ b/libsndio/amsg.h @@ -19,12 +19,28 @@ #include -/* - * socket and option names +/* + * unix-domain socket name is: + * + * DIR [ '-' UID ] '/' FILE UNIT + * + * example: "/tmp/aucat-1000/aucat0" + * + */ +#define SOCKPATH_DIR "/tmp/aucat" +#define SOCKPATH_FILE "aucat" +#define SOCKPATH_MAX (1 + \ + sizeof(SOCKPATH_DIR) - 1 + \ + sizeof(char) + \ + sizeof(int) * 3 + \ + sizeof(char) + \ + sizeof(SOCKPATH_FILE) - 1 + \ + sizeof(int) * 3) + +/* + * server TCP base port number */ -#define AUCAT_PATH "aucat" #define AUCAT_PORT 11025 -#define DEFAULT_OPT "default" /* * WARNING: since the protocol may be simultaneously used by static diff --git a/libsndio/aucat.c b/libsndio/aucat.c index 6dd88c4..c6a3ac2 100644 --- a/libsndio/aucat.c +++ b/libsndio/aucat.c @@ -244,10 +244,12 @@ _aucat_wdata(struct aucat *hdl, const void *buf, size_t len, static int aucat_mkcookie(unsigned char *cookie) { +#define COOKIE_SUFFIX "/.aucat_cookie" +#define TEMPL_SUFFIX ".XXXXXXXX" struct stat sb; - char *home, path[PATH_MAX], tmp[PATH_MAX]; - ssize_t len; - int fd; + char *home, *path = NULL, *tmp = NULL; + size_t home_len, path_len; + int fd, len; /* * try to load the cookie @@ -255,7 +257,13 @@ aucat_mkcookie(unsigned char *cookie) home = issetugid() ? NULL : getenv("HOME"); if (home == NULL) goto bad_gen; - snprintf(path, PATH_MAX, "%s/.aucat_cookie", home); + home_len = strlen(home); + path = malloc(home_len + sizeof(COOKIE_SUFFIX)); + if (path == NULL) + goto bad_gen; + memcpy(path, home, home_len); + memcpy(path + home_len, COOKIE_SUFFIX, sizeof(COOKIE_SUFFIX)); + path_len = home_len + sizeof(COOKIE_SUFFIX) - 1; fd = open(path, O_RDONLY); if (fd < 0) { if (errno != ENOENT) @@ -280,7 +288,7 @@ aucat_mkcookie(unsigned char *cookie) goto bad_close; } close(fd); - return 1; + goto done; bad_close: close(fd); bad_gen: @@ -290,36 +298,44 @@ bad_gen: #ifdef HAVE_ARC4RANDOM arc4random_buf(cookie, AMSG_COOKIELEN); #else - if (!random_bytes(cookie, AMSG_COOKIELEN)) + if (!random_bytes(cookie, AMSG_COOKIELEN)) { + if (path) + free(path); return 0; + } #endif /* * try to save the cookie */ if (home == NULL) - return 1; - if (strlcpy(tmp, path, PATH_MAX) >= PATH_MAX || - strlcat(tmp, ".XXXXXXXX", PATH_MAX) >= PATH_MAX) { - DPRINTF("%s: too long\n", path); - return 1; - } + goto done; + tmp = malloc(path_len + sizeof(TEMPL_SUFFIX)); + if (tmp == NULL) + goto done; + memcpy(tmp, path, path_len); + memcpy(tmp + path_len, TEMPL_SUFFIX, sizeof(TEMPL_SUFFIX)); fd = mkstemp(tmp); if (fd < 0) { DPERROR(tmp); - return 1; + goto done; } if (write(fd, cookie, AMSG_COOKIELEN) < 0) { DPERROR(tmp); unlink(tmp); close(fd); - return 1; + goto done; } close(fd); if (rename(tmp, path) < 0) { DPERROR(tmp); unlink(tmp); } +done: + if (tmp) + free(tmp); + if (path) + free(path); return 1; } @@ -381,7 +397,7 @@ aucat_connect_un(struct aucat *hdl, unsigned int unit) uid = geteuid(); snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat-%u/%s%u", uid, AUCAT_PATH, unit); + SOCKPATH_DIR "-%u/" SOCKPATH_FILE "%u", uid, unit); ca.sun_family = AF_UNIX; s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) @@ -392,7 +408,7 @@ aucat_connect_un(struct aucat *hdl, unsigned int unit) DPERROR(ca.sun_path); /* try shared server */ snprintf(ca.sun_path, sizeof(ca.sun_path), - "/tmp/aucat/%s%u", AUCAT_PATH, unit); + SOCKPATH_DIR "/" SOCKPATH_FILE "%u", unit); while (connect(s, (struct sockaddr *)&ca, len) < 0) { if (errno == EINTR) continue; diff --git a/libsndio/debug.c b/libsndio/debug.c index c02508c..eebf2bc 100644 --- a/libsndio/debug.c +++ b/libsndio/debug.c @@ -54,3 +54,27 @@ _sndio_parsetype(const char *str, char *type) return NULL; return str; } + +const char * +_sndio_parsenum(const char *str, unsigned int *num, unsigned int max) +{ + const char *p = str; + unsigned int dig, maxq, maxr, val; + + val = 0; + maxq = max / 10; + maxr = max % 10; + for (;;) { + dig = *p - '0'; + if (dig >= 10) + break; + if (val > maxq || (val == maxq && dig > maxr)) + return NULL; + val = val * 10 + dig; + p++; + } + if (p == str) + return NULL; + *num = val; + return p; +} diff --git a/libsndio/debug.h b/libsndio/debug.h index 7594784..2433ace 100644 --- a/libsndio/debug.h +++ b/libsndio/debug.h @@ -22,7 +22,7 @@ #define DPRINTFN(n, ...) \ do { \ - if (_sndio_debug >= (n)) \ + if (_sndio_debug >= (n)) \ fprintf(stderr, __VA_ARGS__); \ } while(0) @@ -47,5 +47,6 @@ extern int _sndio_debug; #endif const char *_sndio_parsetype(const char *, char *); +const char *_sndio_parsenum(const char *, unsigned int *, unsigned int); #endif diff --git a/libsndio/mio_alsa.c b/libsndio/mio_alsa.c index b88ba9a..fa74d4a 100644 --- a/libsndio/mio_alsa.c +++ b/libsndio/mio_alsa.c @@ -31,6 +31,8 @@ #include "debug.h" #include "mio_priv.h" +#define DEVNAME_PREFIX "hw:" + #ifdef DEBUG static snd_output_t *output = NULL; #define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) @@ -40,6 +42,7 @@ static snd_output_t *output = NULL; struct mio_alsa_hdl { struct mio_hdl mio; + char *devname; snd_rawmidi_t *in, *out; int infds, onfds, nfds, events; }; @@ -64,7 +67,7 @@ struct mio_hdl * mio_alsa_open(const char *str, unsigned int mode, int nbio) { struct mio_alsa_hdl *hdl; - char path[PATH_MAX]; + size_t len; int rc; switch (*str) { @@ -84,11 +87,20 @@ mio_alsa_open(const char *str, unsigned int mode, int nbio) if (rc < 0) DALSA("couldn't attach to stderr", rc); #endif - snprintf(path, sizeof(path), "hw:%s", str); + len = strlen(str); + hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX)); + if (hdl->devname == NULL) { + free(hdl); + return NULL; + } + memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1); + memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, str, len + 1); hdl->in = hdl->out = NULL; - rc = snd_rawmidi_open(&hdl->in, &hdl->out, path, SND_RAWMIDI_NONBLOCK); + rc = snd_rawmidi_open(&hdl->in, &hdl->out, + hdl->devname, SND_RAWMIDI_NONBLOCK); if (rc) { DALSA("could't open port", rc); + free(hdl->devname); free(hdl); return NULL; } @@ -111,6 +123,7 @@ mio_alsa_close(struct mio_hdl *sh) snd_rawmidi_drain(hdl->out); snd_rawmidi_close(hdl->out); } + free(hdl->devname); free(hdl); } diff --git a/libsndio/mio_rmidi.c b/libsndio/mio_rmidi.c index 7020f73..6d88976 100644 --- a/libsndio/mio_rmidi.c +++ b/libsndio/mio_rmidi.c @@ -30,6 +30,11 @@ #include "debug.h" #include "mio_priv.h" +#define DEVPATH_PREFIX "/dev/rmidi" +#define DEVPATH_MAX (1 + \ + sizeof(DEVPATH_PREFIX) - 1 + \ + sizeof(int) * 3) + struct mio_rmidi_hdl { struct mio_hdl mio; int fd; @@ -56,22 +61,27 @@ _mio_rmidi_open(const char *str, unsigned int mode, int nbio) { int fd, flags; struct mio_rmidi_hdl *hdl; - char path[PATH_MAX]; + char path[DEVPATH_MAX]; + unsigned int devnum; switch (*str) { case '/': str++; break; default: - DPRINTF("_sio_sun_open: %s: '/' expected\n", str); + DPRINTF("_mio_rmidi_open: %s: '/' expected\n", str); + return NULL; + } + str = _sndio_parsenum(str, &devnum, 255); + if (str == NULL || *str != '\0') { + DPRINTF("_mio_rmidi_open: can't determine device number\n"); return NULL; } hdl = malloc(sizeof(struct mio_rmidi_hdl)); if (hdl == NULL) return NULL; _mio_create(&hdl->mio, &mio_rmidi_ops, mode, nbio); - - snprintf(path, sizeof(path), "/dev/rmidi%s", str); + snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); if (mode == (MIO_OUT | MIO_IN)) flags = O_RDWR; else diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c index 29e1696..66b858f 100644 --- a/libsndio/sio_alsa.c +++ b/libsndio/sio_alsa.c @@ -35,6 +35,8 @@ #include "sio_priv.h" #include "bsd-compat.h" +#define DEVNAME_PREFIX "hw:" + #ifdef DEBUG static snd_output_t *output = NULL; #define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err)) @@ -45,6 +47,7 @@ static snd_output_t *output = NULL; struct sio_alsa_hdl { struct sio_hdl sio; struct sio_par par; + char *devname; snd_pcm_t *opcm; snd_pcm_t *ipcm; unsigned ibpf, obpf; /* bytes per frame */ @@ -273,8 +276,8 @@ struct sio_hdl * _sio_alsa_open(const char *str, unsigned mode, int nbio) { struct sio_alsa_hdl *hdl; - char path[PATH_MAX]; struct sio_par par; + size_t len; int err; switch (*str) { @@ -282,7 +285,7 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) str++; break; default: - DPRINTF("_sio_sun_open: %s: '/' expected\n", str); + DPRINTF("_sio_alsa_open: %s: '/' expected\n", str); return NULL; } hdl = malloc(sizeof(struct sio_alsa_hdl)); @@ -295,10 +298,14 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) if (err < 0) DALSA("couldn't attach to stderr", err); #endif - - snprintf(path, sizeof(path), "hw:%s", str); + len = strlen(str); + hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX)); + if (hdl->devname == NULL) + goto bad_free_hdl; + memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1); + memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, str, len + 1); if (mode & SIO_PLAY) { - err = snd_pcm_open(&hdl->opcm, path, + err = snd_pcm_open(&hdl->opcm, hdl->devname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) { DALSA("couldn't open play stream", err); @@ -306,7 +313,7 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio) } } if (mode & SIO_REC) { - err = snd_pcm_open(&hdl->ipcm, path, + err = snd_pcm_open(&hdl->ipcm, hdl->devname, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if (err < 0) { DALSA("couldn't open rec stream", err); @@ -345,6 +352,8 @@ bad_free_opcm: if (mode & SIO_PLAY) snd_pcm_close(hdl->opcm); bad_free: + free(hdl->devname); +bad_free_hdl: free(hdl); return NULL; } @@ -358,6 +367,7 @@ sio_alsa_close(struct sio_hdl *sh) snd_pcm_close(hdl->opcm); if (hdl->sio.mode & SIO_REC) snd_pcm_close(hdl->ipcm); + free(hdl->devname); free(hdl); } diff --git a/libsndio/sio_sun.c b/libsndio/sio_sun.c index db44f3c..db32661 100644 --- a/libsndio/sio_sun.c +++ b/libsndio/sio_sun.c @@ -34,6 +34,11 @@ #include "sio_priv.h" #include "bsd-compat.h" +#define DEVPATH_PREFIX "/dev/audio" +#define DEVPATH_MAX (1 + \ + sizeof(DEVPATH_PREFIX) - 1 + \ + sizeof(int) * 3) + struct sio_sun_hdl { struct sio_hdl sio; int fd; @@ -332,7 +337,8 @@ _sio_sun_open(const char *str, unsigned int mode, int nbio) struct audio_info aui; struct sio_sun_hdl *hdl; struct sio_par par; - char path[PATH_MAX]; + char path[DEVPATH_MAX]; + unsigned int devnum; switch (*str) { case '/': @@ -342,12 +348,17 @@ _sio_sun_open(const char *str, unsigned int mode, int nbio) DPRINTF("_sio_sun_open: %s: '/' expected\n", str); return NULL; } + str = _sndio_parsenum(str, &devnum, 255); + if (str == NULL || *str != '\0') { + DPRINTF("_sio_sun_open: can't determine device number\n"); + return NULL; + } hdl = malloc(sizeof(struct sio_sun_hdl)); if (hdl == NULL) return NULL; _sio_create(&hdl->sio, &sio_sun_ops, mode, nbio); - snprintf(path, sizeof(path), "/dev/audio%s", str); + snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); if (mode == (SIO_PLAY | SIO_REC)) flags = O_RDWR; else