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; }