chiark / gitweb /
Abolish shared libdisorder; now we use a static one.
[disorder] / lib / speaker.c
CommitLineData
460b9539 1/*
2 * This file is part of DisOrder.
3 * Copyright (C) 2005 Richard Kettlewell
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include <config.h>
22#include "types.h"
23
24#include <sys/socket.h>
25#include <string.h>
26#include <errno.h>
27#include <sys/uio.h>
28
29#include "speaker.h"
30#include "log.h"
31
32void speaker_send(int fd, const struct speaker_message *sm, int datafd) {
33 struct msghdr m;
34 struct iovec iov;
35 union {
36 struct cmsghdr cmsg;
37 char size[CMSG_SPACE(sizeof (int))];
38 } u;
39 int ret;
40
41 memset(&m, 0, sizeof m);
42 m.msg_iov = &iov;
43 m.msg_iovlen = 1;
44 iov.iov_base = (void *)sm;
45 iov.iov_len = sizeof *sm;
46 if(datafd != -1) {
47 m.msg_control = (void *)&u.cmsg;
48 m.msg_controllen = sizeof u;
49 memset(&u, 0, sizeof u);
50 u.cmsg.cmsg_len = CMSG_LEN(sizeof (int));
51 u.cmsg.cmsg_level = SOL_SOCKET;
52 u.cmsg.cmsg_type = SCM_RIGHTS;
53 *(int *)CMSG_DATA(&u.cmsg) = datafd;
54 }
55 do {
56 ret = sendmsg(fd, &m, 0);
57 } while(ret < 0 && errno == EINTR);
58 if(ret < 0)
59 fatal(errno, "sendmsg");
60}
61
62int speaker_recv(int fd, struct speaker_message *sm, int *datafd) {
63 struct msghdr m;
64 struct iovec iov;
65 union {
66 struct cmsghdr cmsg;
67 char size[CMSG_SPACE(sizeof (int))];
68 } u;
69 int ret;
70
71 memset(&m, 0, sizeof m);
72 m.msg_iov = &iov;
73 m.msg_iovlen = 1;
74 iov.iov_base = (void *)sm;
75 iov.iov_len = sizeof *sm;
76 if(datafd) {
77 m.msg_control = (void *)&u.cmsg;
78 m.msg_controllen = sizeof u;
79 memset(&u, 0, sizeof u);
80 u.cmsg.cmsg_len = CMSG_LEN(sizeof (int));
81 u.cmsg.cmsg_level = SOL_SOCKET;
82 u.cmsg.cmsg_type = SCM_RIGHTS;
83 *datafd = -1;
84 }
85 do {
86 ret = recvmsg(fd, &m, MSG_DONTWAIT);
87 } while(ret < 0 && errno == EINTR);
88 if(ret < 0) {
89 if(errno != EAGAIN) fatal(errno, "recvmsg");
90 return -1;
91 }
92 if((size_t)m.msg_controllen >= CMSG_LEN(sizeof (int))) {
93 if(!datafd)
94 fatal(0, "got an unexpected file descriptor from recvmsg");
95 else
96 *datafd = *(int *)CMSG_DATA(&u.cmsg);
97 }
98 return ret;
99}
100
101/*
102Local Variables:
103c-basic-offset:2
104comment-column:40
105fill-column:79
106indent-tabs-mode:nil
107End:
108*/