chiark / gitweb /
fishdescriptor: wip reconsider approach
[chiark-utils.git] / fishdescriptor / donate.c
index 60ca2666379bfaed7e52d1c38411349905057638..11c51dbf8cc86ea507f1306efce0dff23a5ba25e 100644 (file)
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* return conventions: functions here return errno values */
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 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;
 }