From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9796 invoked by alias); 28 May 2002 22:35:41 -0000 Mailing-List: contact cygwin-help@cygwin.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner@cygwin.com Mail-Followup-To: cygwin@cygwin.com Received: (qmail 9789 invoked from network); 28 May 2002 22:35:40 -0000 Received: from unknown (HELO pacific-carrier-annex.mit.edu) (18.7.21.83) by sources.redhat.com with SMTP; 28 May 2002 22:35:40 -0000 Received: from grand-central-station.mit.edu (GRAND-CENTRAL-STATION.MIT.EDU [18.7.21.82]) by pacific-carrier-annex.mit.edu (8.9.2/8.9.2) with ESMTP id SAA23403 for ; Tue, 28 May 2002 18:35:39 -0400 (EDT) Received: from manawatu-mail-centre.mit.edu (MANAWATU-MAIL-CENTRE.MIT.EDU [18.7.7.71]) by grand-central-station.mit.edu (8.9.2/8.9.2) with ESMTP id SAA09402 for ; Tue, 28 May 2002 18:35:38 -0400 (EDT) Received: from cathedral-seven.mit.edu (CATHEDRAL-SEVEN.MIT.EDU [18.7.16.65]) by manawatu-mail-centre.mit.edu (8.9.2/8.9.2) with ESMTP id SAA13000 for ; Tue, 28 May 2002 18:35:38 -0400 (EDT) Received: from localhost (davie@localhost) by cathedral-seven.mit.edu (8.9.3) with ESMTP id SAA04405; Tue, 28 May 2002 18:35:38 -0400 (EDT) Date: Wed, 29 May 2002 01:46:00 -0000 From: David E Euresti To: Subject: File Descriptor passing fun Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2002-05/txt/msg01734.txt.bz2 Hi, I wanted to submit my code to pass file descriptors in cygwin. typedef u_int SOCKET; #include #include #include #define DEADBEEF 3735928559 //extern void sfs_warn (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); const char *windows_device_names[] = { NULL, "\\dev\\console", "conin", "conout", "\\dev\\ttym", "\\dev\\tty%d", "\\dev\\ptym", "\\\\.\\com%d", "\\dev\\pipe", "\\dev\\piper", "\\dev\\pipew", "/dev/udp", "\\dev\\windows", NULL, NULL, NULL, "\\dev\\disk", "\\dev\\fd%d", "\\dev\\st%d", "nul", "\\dev\\zero", "\\dev\\%srandom", "\\dev\\mem", "\\dev\\clipboard", "\\dev\\dsp" }; struct passfd { unsigned int uiMagic; DWORD dwProcessID; HANDLE hHandle; BOOL bBinary; BOOL bRead; BOOL bWrite; DWORD dwDevice; }; int getmode (int fd); int parse_fdp(struct passfd *fdp) { BOOL bOk; int fd; int gread, gwrite; HANDLE hOther, hThis = NULL; HANDLE h = NULL; //sfs_warn("Received ProcId %d, Handle 0x%x, Device:%d\n",fdp->dwProcessID, fdp->hHandle, fdp->dwDevice); hOther = OpenProcess(PROCESS_DUP_HANDLE, FALSE, fdp->dwProcessID); hThis = OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId()); bOk = DuplicateHandle(hOther, fdp->hHandle, hThis, &h, 0, TRUE, DUPLICATE_SAME_ACCESS); if (!bOk) { //sfs_warn("Error in Duplicate Handle"); return -1; } CloseHandle(hOther); CloseHandle(hThis); //sfs_warn("It is a %s type handle",(char*) windows_device_names[fdp->dwDevice]); gread = (fdp->bRead ? GENERIC_READ : 0); gwrite = (fdp->bWrite ? GENERIC_WRITE : 0); fd = cygwin32_attach_handle_to_fd((char*) windows_device_names[fdp->dwDevice], -1, h, fdp->bBinary, gread | gwrite); //sfs_warn("attach handle %d\n", fd); return fd; } ssize_t writevfd (int fd, const struct iovec *iov, int iovcnt, int wfd) { struct passfd fdp[1]; struct stat sbuf; int tot = 0; int i, ret; char *buf,*p; struct sockaddr sa; int sal = sizeof (sa); //sfs_warn("Sending fd\n"); fstat(wfd, &sbuf); fdp->uiMagic = DEADBEEF; fdp->dwProcessID = GetCurrentProcessId(); fdp->hHandle = (HANDLE) get_osfhandle(wfd); fdp->bBinary = getmode(wfd); fdp->bRead = sbuf.st_mode & S_IRUSR; fdp->bWrite = sbuf.st_mode & S_IWUSR; fdp->dwDevice = sbuf.st_dev>>8; if ((fdp->dwDevice == 0) && getpeername (fd, &sa, &sal) == 0) fdp->dwDevice = 11; // CYGWIN magic number. //sfs_warn("Sending fd: %d, ProcId %d, Handle 0x%x, Device:%d\n",wfd, fdp->dwProcessID, fdp->hHandle, fdp->dwDevice); for(i = 0; i < iovcnt; ++i) tot += iov[i].iov_len; buf = (char *) malloc(tot+sizeof(struct passfd)); if (tot != 0 && buf == NULL) { errno = ENOMEM; return -1; } p = buf; memcpy(p, fdp, sizeof(struct passfd)); p+= sizeof(struct passfd); for (i = 0; i < iovcnt; ++i) { memcpy (p, iov[i].iov_base, iov[i].iov_len); p += iov[i].iov_len; } ret = send (fd, buf, tot+sizeof(struct passfd), 0); free (buf); if (ret >= sizeof(struct passfd)) return ret-sizeof(struct passfd); else return ret; } ssize_t readvfd (int fd, const struct iovec *iov, int iovcnt, int *rfdp) { int i; struct passfd fdp[1]; int ret, nb; size_t tot = 0; char *buf, *p; //sfs_warn("Read fd\n"); for(i = 0; i < iovcnt; ++i) tot += iov[i].iov_len; buf = (char *) malloc(tot+sizeof(struct passfd)); if (tot != 0 && buf == NULL) { errno = ENOMEM; return -1; } nb = ret = recv (fd, buf, tot+sizeof(struct passfd), 0); p = buf; if (nb >= sizeof(struct passfd)) { memcpy(fdp, buf, sizeof(struct passfd)); if (fdp->uiMagic == DEADBEEF) { //sfs_warn("Actually an fd!\n"); p += sizeof(struct passfd); nb -= sizeof(struct passfd); *rfdp = parse_fdp(fdp); ret = nb; } } while (nb > 0) { ssize_t cnt = min(nb, iov->iov_len); memcpy (iov->iov_base, p, cnt); p += cnt; nb -= cnt; ++iov; } free(buf); if (*rfdp >= 0 && ret == 0) { ret = -1; errno = EAGAIN; } return ret; } Unfortunately it suffers from lineup issues. If you try to send data, then a file descriptor, then more data, the reader will get lost and not find any file descriptor and return data that you never really sent. If anybody has any other ideas about how to do this, let me know. Once it's fixed I'm sure this code will be useful in cygwin. David -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/