X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=blobdiff_plain;f=fishdescriptor%2Fdonate.c;h=11c51dbf8cc86ea507f1306efce0dff23a5ba25e;hp=60ca2666379bfaed7e52d1c38411349905057638;hb=38b9a663b6ca063bf79460c5e7abd1c3c476accb;hpb=95e48f3e3aedce1f276a5f0591f706c2df95ee72
diff --git a/fishdescriptor/donate.c b/fishdescriptor/donate.c
index 60ca266..11c51db 100644
--- a/fishdescriptor/donate.c
+++ b/fishdescriptor/donate.c
@@ -16,10 +16,17 @@
* along with this program. If not, see .
*/
-/* return conventions: functions here return errno values */
+#include
+#include
+#include
+
+#include
+#include
+#include
static int fishdescriptor_sendmsg_fds(int carrier,
int nfds, const int fds[]) {
+ /* return convention: like a syscall */
struct msghdr msg = { 0 };
struct cmsghdr *cmsg;
size_t spaceneeded = nfds * sizeof(fds[0]);
@@ -46,6 +53,40 @@ static int fishdescriptor_sendmsg_fds(int carrier,
msg.msg_controllen = cmsg->cmsg_len;
r = sendmsg(carrier, &msg, 0);
- if (r < 0)
- return 0;
+ if (r < 0) return -1;
+
+ return 0;
+}
+
+int fishdescriptor_donate(const char *path, const int *fds) {
+ /* return convention: returns errno value */
+ /* within function: r is like syscall return, errno value is in errno */
+ int r;
+ int esave = errno;
+ int carrier=-1;
+
+ carrier = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (carrier < 0) { r=-1; goto out; }
+
+ struct sockaddr_un suna;
+ memset(&suna,0,sizeof(suna));
+ suna.sun_family = AF_UNIX;
+ if (strlen(path) >= sizeof(suna.sun_path)) { errno=E2BIG; r=-1; goto out; }
+ strcpy(suna.sun_path, path);
+
+ r = connect(carrier, (const struct sockaddr*)&suna, sizeof(suna));
+ if (r) goto out;
+
+ int nfds;
+ for (nfds=0; fds[nfds] > 0; nfds++);
+
+ r = fishdescriptor_sendmsg_fds(carrier, nfds, fds);
+ if (r) goto out;
+
+ r = 0;
+ out:
+ if (carrier >= 0) close(carrier);
+ r = !r ? 0 : !errno ? EIO : errno;
+ errno = esave;
+ return r;
}