public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* File Descriptor passing fun
@ 2002-05-29  1:46 David E Euresti
  2002-05-29  4:51 ` mkcramfs porting done - device file issues gmx
  0 siblings, 1 reply; 7+ messages in thread
From: David E Euresti @ 2002-05-29  1:46 UTC (permalink / raw)
  To: cygwin

Hi,
	I wanted to submit my code to pass file descriptors in cygwin.

typedef u_int	SOCKET;
#include<windows.h>
#include<io.h>
#include <sys/cygwin.h>
#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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-05-30  8:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-29  1:46 File Descriptor passing fun David E Euresti
2002-05-29  4:51 ` mkcramfs porting done - device file issues gmx
2002-05-29  4:57   ` Christopher Faylor
2002-05-29  6:11     ` Corinna Vinschen
2002-05-29 20:42       ` AW: " gmx
2002-05-29 20:55         ` gmx
2002-05-30  7:24         ` Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).