chiark / gitweb /
fishdescriptor: More work, before trying to compile it
[chiark-utils.git] / fishdescriptor / donate.c
1 /*
2  * Copyright (C) 2009 Citrix Ltd.
3  * Copyright (C) 2017 Citrix Ltd.
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 3 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,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU 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, see <http://www.gnu.org/licenses/>.
17  */
18
19 /* return conventions: functions here return 0 on success,
20  * or -1 setting errno */
21
22 static int fishdescriptor_sendmsg_fds(int carrier,
23                                       int nfds, const int fds[]) {
24   struct msghdr msg = { 0 };
25   struct cmsghdr *cmsg;
26   size_t spaceneeded = nfds * sizeof(fds[0]);
27   char control[CMSG_SPACE(spaceneeded)];
28   struct iovec iov;
29   int r;
30
31   iov.iov_base = &nfds;
32   iov.iov_len  = sizeof(nfds);
33
34   /* compose the message */
35   msg.msg_iov = &iov;
36   msg.msg_iovlen = 1;
37   msg.msg_control = control;
38   msg.msg_controllen = sizeof(control);
39
40   /* attach open fd */
41   cmsg = CMSG_FIRSTHDR(&msg);
42   cmsg->cmsg_level = SOL_SOCKET;
43   cmsg->cmsg_type = SCM_RIGHTS;
44   cmsg->cmsg_len = CMSG_LEN(spaceneeded);
45   memcpy(CMSG_DATA(cmsg), fds, spaceneeded);
46
47   msg.msg_controllen = cmsg->cmsg_len;
48     
49   r = sendmsg(carrier, &msg, 0);
50   if (r < 0) return -1;
51
52   return 0;
53 }
54
55 static int fishdescriptor_donate(const char *path, const int *fds) {
56   int r;
57   int carrier=-1;
58
59   carrier = socket(AF_UNIX, SOCK_STREAM, 0);
60   if (carrier < 0) goto out;
61
62   struct sockaddr_un suna;
63   memset(suna,0,&suna);
64   suna.sun_family = AF_UNIX;
65   if (strlen(path) >= sizeof(suna.sun_path)) { outno = E2BIG; goto out; }
66   strcpy(suna.sun_path, path);
67
68   int r = connect(carrier, &suna, sizeof(suna));
69   if (r) goto out;
70
71   int nfds;
72   for (nfds=0; fds[nfds] > 0; nfds++);
73
74   r = fishdescriptor_sendmsg_fds(carrier, nfds, fds);
75   if (r) goto out;
76
77   r = 0;
78  out:
79   if (carrier >= 0) close(carrier);
80   return r;
81 }