mirror of https://github.com/ericonr/sndio.git
add TCP transport
This commit is contained in:
parent
6c7f04bf10
commit
3f1215502b
|
@ -33,6 +33,7 @@
|
|||
.Op Fl h Ar fmt
|
||||
.Op Fl i Ar file
|
||||
.Op Fl j Ar flag
|
||||
.Op Fl L Ar addr
|
||||
.Op Fl m Ar mode
|
||||
.Op Fl o Ar file
|
||||
.Op Fl q Ar device
|
||||
|
@ -140,6 +141,13 @@ For instance, this feature could be used to request mono streams to
|
|||
be sent on multiple outputs or to record a stereo input into a mono stream.
|
||||
The default is
|
||||
.Ar on .
|
||||
.It Fl L Ar addr
|
||||
Listen on the given address for incoming TCP connections.
|
||||
Without this option,
|
||||
.Nm
|
||||
listens only on the Unix-domain socket, thus it's not reachable
|
||||
from the network.
|
||||
The port number is 6523 plus the unit number.
|
||||
.It Fl l
|
||||
Detach and become a daemon.
|
||||
.It Fl m Ar mode
|
||||
|
|
|
@ -260,6 +260,16 @@ struct cfdev {
|
|||
|
||||
SLIST_HEAD(cfdevlist, cfdev);
|
||||
|
||||
/*
|
||||
* TCP addresses to listen on
|
||||
*/
|
||||
struct cfnet {
|
||||
SLIST_ENTRY(cfnet) entry;
|
||||
char *addr;
|
||||
};
|
||||
|
||||
SLIST_HEAD(cfnetlist, cfnet);
|
||||
|
||||
void
|
||||
cfdev_add(struct cfdevlist *list, struct cfdev *templ, char *path)
|
||||
{
|
||||
|
@ -319,6 +329,20 @@ cfmid_add(struct cfmidlist *list, char *path)
|
|||
SLIST_INSERT_HEAD(list, cm, entry);
|
||||
}
|
||||
|
||||
void
|
||||
cfnet_add(struct cfnetlist *list, char *addr)
|
||||
{
|
||||
struct cfnet *cn;
|
||||
|
||||
cn = malloc(sizeof(struct cfnet));
|
||||
if (cn == NULL) {
|
||||
perror("malloc");
|
||||
abort();
|
||||
}
|
||||
cn->addr = addr;
|
||||
SLIST_INSERT_HEAD(list, cn, entry);
|
||||
}
|
||||
|
||||
void
|
||||
setsig(void)
|
||||
{
|
||||
|
@ -416,11 +440,11 @@ aucat_usage(void)
|
|||
{
|
||||
(void)fputs("usage: " PROG_AUCAT " [-dlnu] [-a flag] [-b nframes] "
|
||||
"[-C min:max] [-c min:max] [-e enc]\n\t"
|
||||
"[-f device] [-h fmt] [-i file] [-j flag] [-m mode]"
|
||||
"[-o file] [-q device]\n\t"
|
||||
"[-r rate] [-s name] [-t mode] [-U unit] "
|
||||
"[-v volume] [-x policy]\n\t"
|
||||
"[-z nframes]\n",
|
||||
"[-f device] [-h fmt] [-i file] [-j flag] [-L addr] [-m mode] "
|
||||
"[-o file]\n\t"
|
||||
"[-q device] [-r rate] [-s name] [-t mode] [-U unit] "
|
||||
"[-v volume]\n\t"
|
||||
"[-x policy] [-z nframes]\n",
|
||||
stderr);
|
||||
}
|
||||
|
||||
|
@ -428,10 +452,11 @@ int
|
|||
aucat_main(int argc, char **argv)
|
||||
{
|
||||
struct cfdevlist cfdevs;
|
||||
struct cfnetlist cfnets;
|
||||
struct cfmid *cm;
|
||||
struct cfstr *cs;
|
||||
struct cfdev *cd;
|
||||
struct listen *listen = NULL;
|
||||
struct cfnet *cn;
|
||||
int c, u_flag, d_flag, l_flag, n_flag, unit;
|
||||
char base[PATH_MAX], path[PATH_MAX];
|
||||
unsigned mode, rate;
|
||||
|
@ -450,6 +475,7 @@ aucat_main(int argc, char **argv)
|
|||
l_flag = 0;
|
||||
n_flag = 0;
|
||||
SLIST_INIT(&cfdevs);
|
||||
SLIST_INIT(&cfnets);
|
||||
nfile = nsock = 0;
|
||||
|
||||
/*
|
||||
|
@ -488,7 +514,7 @@ aucat_main(int argc, char **argv)
|
|||
cd->round = 0;
|
||||
cd->hold = 1;
|
||||
|
||||
while ((c = getopt(argc, argv, "a:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:t:j:z:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "a:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:L:t:j:z:")) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
#ifdef DEBUG
|
||||
|
@ -508,6 +534,9 @@ aucat_main(int argc, char **argv)
|
|||
if (str)
|
||||
errx(1, "%s: unit number is %s", optarg, str);
|
||||
break;
|
||||
case 'L':
|
||||
cfnet_add(&cfnets, optarg);
|
||||
break;
|
||||
case 'm':
|
||||
cs->mode = opt_mode();
|
||||
cd->mode = cs->mode;
|
||||
|
@ -768,9 +797,12 @@ aucat_main(int argc, char **argv)
|
|||
if (nsock > 0) {
|
||||
snprintf(path, sizeof(path), "%s/%s%u", base,
|
||||
AUCAT_PATH, unit);
|
||||
listen = listen_new(&listen_ops, path);
|
||||
if (listen == NULL)
|
||||
exit(1);
|
||||
listen_new_un(path);
|
||||
while (!SLIST_EMPTY(&cfnets)) {
|
||||
cn = SLIST_FIRST(&cfnets);
|
||||
SLIST_REMOVE_HEAD(&cfnets, entry);
|
||||
listen_new_tcp(cn->addr, AUCAT_PORT + unit);
|
||||
}
|
||||
}
|
||||
if (geteuid() == 0)
|
||||
privdrop();
|
||||
|
@ -805,8 +837,8 @@ aucat_main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
fatal:
|
||||
if (nsock > 0)
|
||||
file_close(&listen->file);
|
||||
listen_closeall();
|
||||
|
||||
/*
|
||||
* give a chance to drain
|
||||
*/
|
||||
|
@ -830,7 +862,7 @@ void
|
|||
midicat_usage(void)
|
||||
{
|
||||
(void)fputs("usage: " PROG_MIDICAT " [-dl] "
|
||||
"[-i file] [-o file] [-q port] [-s name] [-U unit]\n",
|
||||
"[-i file] [-L addr] [-o file] [-q port] [-s name] [-U unit]\n",
|
||||
stderr);
|
||||
}
|
||||
|
||||
|
@ -838,10 +870,11 @@ int
|
|||
midicat_main(int argc, char **argv)
|
||||
{
|
||||
struct cfdevlist cfdevs;
|
||||
struct cfnetlist cfnets;
|
||||
struct cfmid *cm;
|
||||
struct cfstr *cs;
|
||||
struct cfdev *cd;
|
||||
struct listen *listen = NULL;
|
||||
struct cfnet *cn;
|
||||
int c, d_flag, l_flag, unit, fd;
|
||||
char base[PATH_MAX], path[PATH_MAX];
|
||||
struct file *stdx;
|
||||
|
@ -858,6 +891,7 @@ midicat_main(int argc, char **argv)
|
|||
d_flag = 0;
|
||||
l_flag = 0;
|
||||
SLIST_INIT(&cfdevs);
|
||||
SLIST_INIT(&cfnets);
|
||||
nsock = 0;
|
||||
|
||||
/*
|
||||
|
@ -916,6 +950,9 @@ midicat_main(int argc, char **argv)
|
|||
if (str)
|
||||
errx(1, "%s: unit number is %s", optarg, str);
|
||||
break;
|
||||
case 'L':
|
||||
cfnet_add(&cfnets, optarg);
|
||||
break;
|
||||
default:
|
||||
midicat_usage();
|
||||
exit(1);
|
||||
|
@ -1038,9 +1075,12 @@ midicat_main(int argc, char **argv)
|
|||
if (nsock > 0) {
|
||||
snprintf(path, sizeof(path), "%s/%s%u", base,
|
||||
MIDICAT_PATH, unit);
|
||||
listen = listen_new(&listen_ops, path);
|
||||
if (listen == NULL)
|
||||
exit(1);
|
||||
listen_new_un(path);
|
||||
while (!SLIST_EMPTY(&cfnets)) {
|
||||
cn = SLIST_FIRST(&cfnets);
|
||||
SLIST_REMOVE_HEAD(&cfnets, entry);
|
||||
listen_new_tcp(cn->addr, MIDICAT_PORT + unit);
|
||||
}
|
||||
}
|
||||
if (geteuid() == 0)
|
||||
privdrop();
|
||||
|
@ -1068,8 +1108,8 @@ midicat_main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
fatal:
|
||||
if (nsock > 0)
|
||||
file_close(&listen->file);
|
||||
listen_closeall();
|
||||
|
||||
/*
|
||||
* give a chance to drain
|
||||
*/
|
||||
|
|
|
@ -35,6 +35,8 @@ extern int debug_level;
|
|||
*/
|
||||
#define MIDICAT_PATH "midicat"
|
||||
#define AUCAT_PATH "aucat"
|
||||
#define MIDICAT_PORT 6533
|
||||
#define AUCAT_PORT 6523
|
||||
#define DEFAULT_OPT "default"
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -29,6 +32,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "listen.h"
|
||||
#include "sock.h"
|
||||
#ifdef COMPAT_STRLCPY
|
||||
|
@ -48,8 +52,8 @@ struct fileops listen_ops = {
|
|||
listen_revents
|
||||
};
|
||||
|
||||
struct listen *
|
||||
listen_new(struct fileops *ops, char *path)
|
||||
void
|
||||
listen_new_un(char *path)
|
||||
{
|
||||
int sock, oldumask;
|
||||
struct sockaddr_un sockname;
|
||||
|
@ -58,7 +62,7 @@ listen_new(struct fileops *ops, char *path)
|
|||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
perror("socket");
|
||||
return NULL;
|
||||
exit(1);
|
||||
}
|
||||
if (unlink(path) < 0 && errno != ENOENT) {
|
||||
perror("unlink");
|
||||
|
@ -77,7 +81,7 @@ listen_new(struct fileops *ops, char *path)
|
|||
perror("listen");
|
||||
goto bad_close;
|
||||
}
|
||||
f = (struct listen *)file_new(ops, path, 1);
|
||||
f = (struct listen *)file_new(&listen_ops, path, 1);
|
||||
if (f == NULL)
|
||||
goto bad_close;
|
||||
f->path = strdup(path);
|
||||
|
@ -86,10 +90,70 @@ listen_new(struct fileops *ops, char *path)
|
|||
exit(1);
|
||||
}
|
||||
f->fd = sock;
|
||||
return f;
|
||||
return;
|
||||
bad_close:
|
||||
close(sock);
|
||||
return NULL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
listen_new_tcp(char *addr, unsigned port)
|
||||
{
|
||||
char serv[sizeof(unsigned) * 3 + 1];
|
||||
struct addrinfo *ailist, *ai, aihints;
|
||||
struct listen *f;
|
||||
int s, error, opt = 1, n = 0;
|
||||
|
||||
/*
|
||||
* obtain a list of possible addresses for the host/port
|
||||
*/
|
||||
memset(&aihints, 0, sizeof(struct addrinfo));
|
||||
snprintf(serv, sizeof(serv), "%u", port);
|
||||
aihints.ai_flags |= AI_PASSIVE;
|
||||
aihints.ai_socktype = SOCK_STREAM;
|
||||
aihints.ai_protocol = IPPROTO_TCP;
|
||||
error = getaddrinfo(addr, serv, &aihints, &ailist);
|
||||
if (error) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* for each address, try create a listening socket bound on
|
||||
* that address
|
||||
*/
|
||||
for (ai = ailist; ai != NULL; ai = ai->ai_next) {
|
||||
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (s < 0) {
|
||||
perror("socket");
|
||||
continue;
|
||||
}
|
||||
opt = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) {
|
||||
perror("setsockopt");
|
||||
goto bad_close;
|
||||
}
|
||||
if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
perror("bind");
|
||||
goto bad_close;
|
||||
}
|
||||
if (listen(s, 1) < 0) {
|
||||
perror("listen");
|
||||
goto bad_close;
|
||||
}
|
||||
f = (struct listen *)file_new(&listen_ops, addr, 1);
|
||||
if (f == NULL) {
|
||||
bad_close:
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
f->path = NULL;
|
||||
f->fd = s;
|
||||
n++;
|
||||
}
|
||||
freeaddrinfo(ailist);
|
||||
if (n == 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -119,6 +183,7 @@ listen_revents(struct file *file, struct pollfd *pfd)
|
|||
caddrlen = sizeof(caddrlen);
|
||||
sock = accept(f->fd, &caddr, &caddrlen);
|
||||
if (sock < 0) {
|
||||
/* XXX: should kill the socket */
|
||||
perror("accept");
|
||||
return 0;
|
||||
}
|
||||
|
@ -140,7 +205,21 @@ listen_close(struct file *file)
|
|||
{
|
||||
struct listen *f = (struct listen *)file;
|
||||
|
||||
if (f->path != NULL) {
|
||||
unlink(f->path);
|
||||
free(f->path);
|
||||
}
|
||||
close(f->fd);
|
||||
}
|
||||
|
||||
void
|
||||
listen_closeall(void)
|
||||
{
|
||||
struct file *f, *fnext;
|
||||
|
||||
for (f = LIST_FIRST(&file_list); f != NULL; f = fnext) {
|
||||
fnext = LIST_NEXT(f, entry);
|
||||
if (f->ops == &listen_ops)
|
||||
file_close(f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: listen.h,v 1.5 2009/07/25 10:52:19 ratchov Exp $ */
|
||||
/* $OpenBSD$ */
|
||||
/*
|
||||
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
|
||||
*
|
||||
|
@ -28,11 +28,12 @@ struct listen {
|
|||
int fd;
|
||||
};
|
||||
|
||||
struct listen *listen_new(struct fileops *, char *);
|
||||
void listen_new_un(char *);
|
||||
void listen_new_tcp(char *, unsigned);
|
||||
int listen_nfds(struct file *);
|
||||
int listen_pollfd(struct file *, struct pollfd *, int);
|
||||
int listen_revents(struct file *, struct pollfd *);
|
||||
void listen_close(struct file *);
|
||||
extern struct fileops listen_ops;
|
||||
void listen_closeall(void);
|
||||
|
||||
#endif /* !defined(LISTEN_H) */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
.Nm midicat
|
||||
.Op Fl dl
|
||||
.Op Fl i Ar file
|
||||
.Op Fl L Ar addr
|
||||
.Op Fl o Ar file
|
||||
.Op Fl q Ar port
|
||||
.Op Fl s Ar name
|
||||
|
@ -57,6 +58,13 @@ Read data to send from this file.
|
|||
If the option argument is
|
||||
.Sq -
|
||||
then standard input will be used.
|
||||
.It Fl L Ar addr
|
||||
Listen on the given address for incoming TCP connections.
|
||||
Without this option,
|
||||
.Nm
|
||||
listens only on the Unix-domain socket, thus it's not reachable
|
||||
from the network.
|
||||
The port number is 6533 plus the unit number.
|
||||
.It Fl l
|
||||
Detach and become a daemon.
|
||||
.It Fl o Ar file
|
||||
|
|
|
@ -47,7 +47,7 @@ case `uname` in
|
|||
so="$so libsndio.so.\${MAJ} libsndio.so"
|
||||
defs='-DCOMPAT_GETPEEREID -DCOMPAT_ISSETUGID \\\
|
||||
-DCOMPAT_STRLCPY -DCOMPAT_STRTONUM \\\
|
||||
-DCOMPAT_LETOH -DCOMPAT_PACKED'
|
||||
-DCOMPAT_LETOH -DCOMPAT_PACKED -DDEV_RANDOM=\\"/dev/urandom\\"'
|
||||
;;
|
||||
OpenBSD)
|
||||
sun=yes
|
||||
|
|
176
libsndio/aucat.c
176
libsndio/aucat.c
|
@ -19,7 +19,8 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h> /* IPPROTO_XXX */
|
||||
#include <netdb.h> /* gethostbyname */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "sndio.h"
|
||||
|
||||
#include "aucat.h"
|
||||
#include "debug.h"
|
||||
|
@ -35,6 +37,10 @@
|
|||
#include "bsd-compat.h"
|
||||
#endif
|
||||
|
||||
#ifndef DEV_RANDOM
|
||||
#define DEV_RANDOM "/dev/arandom"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* read a message, return 0 if not completed
|
||||
*/
|
||||
|
@ -199,7 +205,26 @@ aucat_wdata(struct aucat *hdl, const void *buf, size_t len, unsigned wbpf, int *
|
|||
int
|
||||
aucat_gencookie(unsigned char *cookie)
|
||||
{
|
||||
arc4random_buf(cookie, AMSG_COOKIELEN);
|
||||
int fd;
|
||||
ssize_t n, len;
|
||||
|
||||
fd = open(DEV_RANDOM, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
DPERROR(DEV_RANDOM);
|
||||
return 0;
|
||||
}
|
||||
len = AMSG_COOKIELEN;
|
||||
while (len > 0) {
|
||||
n = read(fd, cookie, AMSG_COOKIELEN);
|
||||
if (n < 0) {
|
||||
DPERROR(DEV_RANDOM);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
cookie += n;
|
||||
len -= n;
|
||||
}
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -260,16 +285,121 @@ bad_gen:
|
|||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
aucat_connect_tcp(struct aucat *hdl, char *host, char *unit, unsigned mode)
|
||||
{
|
||||
int s, error;
|
||||
struct addrinfo *ailist, *ai, aihints;
|
||||
unsigned port;
|
||||
char serv[NI_MAXSERV];
|
||||
|
||||
if (sscanf(unit, "%u", &port) != 1) {
|
||||
DPRINTF("%s: bad unit number\n", unit);
|
||||
return 0;
|
||||
}
|
||||
if (mode & (MIO_IN | MIO_OUT)) {
|
||||
port += MIDICAT_PORT;
|
||||
} else if (mode & (SIO_PLAY | SIO_REC)) {
|
||||
port += AUCAT_PORT;
|
||||
} else {
|
||||
DPRINTF("aucat_connect_tcp: unknown mode\n");
|
||||
abort();
|
||||
}
|
||||
snprintf(serv, sizeof(serv), "%u", port);
|
||||
memset(&aihints, 0, sizeof(struct addrinfo));
|
||||
aihints.ai_socktype = SOCK_STREAM;
|
||||
aihints.ai_protocol = IPPROTO_TCP;
|
||||
error = getaddrinfo(host, serv, &aihints, &ailist);
|
||||
if (error) {
|
||||
DPRINTF("%s: %s\n", host, gai_strerror(error));
|
||||
return 0;
|
||||
}
|
||||
s = -1;
|
||||
for (ai = ailist; ai != NULL; ai = ai->ai_next) {
|
||||
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (s < 0) {
|
||||
DPERROR("socket");
|
||||
continue;
|
||||
}
|
||||
if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
DPERROR("connect");
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(ailist);
|
||||
if (s < 0)
|
||||
return 0;
|
||||
hdl->fd = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
aucat_connect_un(struct aucat *hdl, char *unit, unsigned mode)
|
||||
{
|
||||
struct sockaddr_un ca;
|
||||
socklen_t len = sizeof(struct sockaddr_un);
|
||||
char *sock;
|
||||
uid_t uid;
|
||||
int s;
|
||||
|
||||
if (mode & (MIO_IN | MIO_OUT)) {
|
||||
sock = MIDICAT_PATH;
|
||||
} else if (mode & (SIO_PLAY | SIO_REC)) {
|
||||
sock = AUCAT_PATH;
|
||||
} else {
|
||||
DPRINTF("aucat_connect_un: unknown mode\n");
|
||||
abort();
|
||||
}
|
||||
uid = geteuid();
|
||||
snprintf(ca.sun_path, sizeof(ca.sun_path),
|
||||
"/tmp/aucat-%u/%s%s", uid, sock, unit);
|
||||
ca.sun_family = AF_UNIX;
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
return 0;
|
||||
while (connect(s, (struct sockaddr *)&ca, len) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
DPERROR("aucat_init: connect");
|
||||
/* try shared server */
|
||||
snprintf(ca.sun_path, sizeof(ca.sun_path),
|
||||
"/tmp/aucat/%s%s", sock, unit);
|
||||
while (connect(s, (struct sockaddr *)&ca, len) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
DPERROR("aucat_init: connect");
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
hdl->fd = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
aucat_open(struct aucat *hdl, const char *str, char *sock, unsigned mode, int nbio)
|
||||
{
|
||||
extern char *__progname;
|
||||
int s, eof;
|
||||
int eof, hashost;
|
||||
char unit[4], *sep, *opt;
|
||||
struct sockaddr_un ca;
|
||||
socklen_t len = sizeof(struct sockaddr_un);
|
||||
uid_t uid;
|
||||
char host[NI_MAXHOST];
|
||||
|
||||
sep = strchr(str, '/');
|
||||
if (sep == NULL) {
|
||||
hashost = 0;
|
||||
} else {
|
||||
if (sep - str >= sizeof(host)) {
|
||||
DPRINTF("aucat_open: %s: host too long\n", str);
|
||||
return 0;
|
||||
}
|
||||
memcpy(host, str, sep - str);
|
||||
host[sep - str] = '\0';
|
||||
hashost = 1;
|
||||
str = sep + 1;
|
||||
}
|
||||
sep = strchr(str, '.');
|
||||
if (sep == NULL) {
|
||||
opt = "default";
|
||||
|
@ -283,36 +413,17 @@ aucat_open(struct aucat *hdl, const char *str, char *sock, unsigned mode, int nb
|
|||
strlcpy(unit, str, opt - str);
|
||||
}
|
||||
DPRINTF("aucat_init: trying %s -> %s.%s\n", str, unit, opt);
|
||||
uid = geteuid();
|
||||
if (strchr(str, '/') != NULL)
|
||||
if (hashost) {
|
||||
if (!aucat_connect_tcp(hdl, host, unit, mode))
|
||||
return 0;
|
||||
} else {
|
||||
if (!aucat_connect_un(hdl, unit, mode))
|
||||
return 0;
|
||||
snprintf(ca.sun_path, sizeof(ca.sun_path),
|
||||
"/tmp/aucat-%u/%s%s", uid, sock, unit);
|
||||
ca.sun_family = AF_UNIX;
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
goto bad_free;
|
||||
while (connect(s, (struct sockaddr *)&ca, len) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
DPERROR("aucat_init: connect");
|
||||
/* try shared server */
|
||||
snprintf(ca.sun_path, sizeof(ca.sun_path),
|
||||
"/tmp/aucat/%s%s", sock, unit);
|
||||
while (connect(s, (struct sockaddr *)&ca, len) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
DPERROR("aucat_init: connect");
|
||||
goto bad_connect;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (fcntl(s, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
if (fcntl(hdl->fd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
DPERROR("FD_CLOEXEC");
|
||||
goto bad_connect;
|
||||
}
|
||||
hdl->fd = s;
|
||||
hdl->rstate = RSTATE_MSG;
|
||||
hdl->rtodo = sizeof(struct amsg);
|
||||
hdl->wstate = WSTATE_IDLE;
|
||||
|
@ -350,9 +461,8 @@ aucat_open(struct aucat *hdl, const char *str, char *sock, unsigned mode, int nb
|
|||
}
|
||||
return 1;
|
||||
bad_connect:
|
||||
while (close(s) < 0 && errno == EINTR)
|
||||
while (close(hdl->fd) < 0 && errno == EINTR)
|
||||
; /* retry */
|
||||
bad_free:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue