home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / pty4 / part03 / ptycomm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-19  |  3.4 KB  |  185 lines

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <sys/socket.h>
  4. #include <sys/un.h>
  5. #include <sys/uio.h>
  6. #include <errno.h>
  7. extern int errno;
  8. #include "fmt.h"
  9. #include "config/ptyext.h"
  10. #include "ptycomm.h"
  11. #include "ptymisc.h"
  12.  
  13. /*
  14. Under most versions of SunOS and Ultrix, as well as lots of other systems,
  15. file descriptor passing doesn't work. The most important problem is that
  16. in some situations recvmsg() may return 0 without actually waiting to
  17. receive the file descriptors; in other words, msg_accrightslen may be
  18. sporadically 0. The workaround here is to pause very briefly (1/100 of a
  19. second) and try the recvmsg() again, up to 100 times. I'd prefer seeing
  20. the bug fixed.
  21. */
  22.  
  23. #define ESTUPID EINPROGRESS /* [sigh] */
  24.  
  25. static int comm_path(s,ext,uid)
  26. char *s;
  27. char *ext;
  28. int uid;
  29. {
  30.  int i;
  31.  char *t;
  32.  
  33. /* as a last layer of protection we make sure that we only create */
  34. /* valid filenames... */
  35.  for (i = 0;PTYEXT1[i];++i)
  36.    if (ext[0] == PTYEXT1[i])
  37.      break;
  38.  if (!PTYEXT1[i])
  39.    return -1;
  40.  for (i = 0;PTYEXT2[i];++i)
  41.    if (ext[1] == PTYEXT2[i])
  42.      break;
  43.  if (!PTYEXT2[i])
  44.    return -1;
  45.  t = s;
  46.  t += fmt_strncpy(t,"comm.",0);
  47.  t += fmt_uint(t,uid);
  48.  *t++ = '.';
  49.  *t++ = ext[0];
  50.  *t++ = ext[1];
  51.  *t = 0;
  52.  return 0;
  53. }
  54.  
  55. int comm_read(ext,uid)
  56. char *ext;
  57. int uid;
  58. {
  59.  int s;
  60.  struct sockaddr_un sa;
  61.  
  62.  if ((s = socket(AF_UNIX,SOCK_STREAM,0)) == -1)
  63.    return -1;
  64.  sa.sun_family = AF_UNIX;
  65.  if (comm_path(sa.sun_path,ext,uid) == -1)
  66.    return -1;
  67.  unlink(sa.sun_path);
  68.  if (bind(s,(struct sockaddr *) &sa,strlen(sa.sun_path) + 2) == -1)
  69.    return -1;
  70.  if (listen(s,5) == -1)
  71.    return -1;
  72.  return s;
  73. }
  74.  
  75. int comm_accept(fd)
  76. int fd;
  77. {
  78.  struct sockaddr_un sa;
  79.  int salen;
  80.  salen = sizeof(sa);
  81.  return accept(fd,(struct sockaddr *) &sa,&salen);
  82. }
  83.  
  84. int comm_unlink(ext,uid)
  85. char *ext;
  86. int uid;
  87. {
  88.  struct sockaddr_un sa;
  89.  if (comm_path(sa.sun_path,ext,uid) == -1)
  90.    return -1;
  91.  return unlink(sa.sun_path);
  92. }
  93.  
  94. int comm_write(ext,uid)
  95. char *ext;
  96. int uid;
  97. {
  98.  int s;
  99.  struct sockaddr_un sa;
  100.  
  101.  if ((s = socket(AF_UNIX,SOCK_STREAM,0)) == -1)
  102.    return -1;
  103.  sa.sun_family = AF_UNIX;
  104.  if (comm_path(sa.sun_path,ext,uid) == -1)
  105.    return -1;
  106.  if (connect(s,(struct sockaddr *) &sa,strlen(sa.sun_path) + 2) == -1)
  107.    return -1;
  108.  return s;
  109. }
  110.  
  111. int csp(fdcomm,fd)
  112. int fdcomm;
  113. int fd;
  114. {
  115.  struct msghdr msg[2];
  116.  int acc[5];
  117.  struct iovec i[2];
  118.  
  119.  msg[0].msg_name = 0;
  120.  msg[0].msg_namelen = 0;
  121.  msg[0].msg_iov = i; /* grrrr */
  122.  msg[0].msg_iovlen = 0;
  123.  msg[0].msg_accrights = (caddr_t) acc;
  124.  msg[0].msg_accrightslen = sizeof(int);
  125.  
  126.  acc[0] = fd;
  127.  
  128.  return sendmsg(fdcomm,msg,0);
  129. }
  130.  
  131. int comm_putfd(fdcomm,fd)
  132. int fdcomm;
  133. int fd;
  134. {
  135.  int tries;
  136.  for (tries = 0;tries < 100;++tries)
  137.    if (csp(fdcomm,fd) == 0)
  138.      return 0;
  139.  return -1;
  140. }
  141.  
  142. static int cgf(fdcomm)
  143. int fdcomm;
  144. {
  145.  struct msghdr msg[2];
  146.  int acc[5];
  147.  struct iovec i[2];
  148.  int r;
  149.  
  150.  msg[0].msg_name = 0;
  151.  msg[0].msg_namelen = 0;
  152.  msg[0].msg_iov = i; /* grrrr */
  153.  msg[0].msg_iovlen = 0;
  154.  msg[0].msg_accrights = (caddr_t) acc;
  155.  msg[0].msg_accrightslen = sizeof(int);
  156.  
  157.  do
  158.    r = recvmsg(fdcomm,msg,0);
  159.  while ((r == -1) && ((errno == EINTR) || (errno == EWOULDBLOCK)));
  160.  if (r == -1)
  161.    return -1;
  162.  if (msg[0].msg_accrightslen != sizeof(int))
  163.   {
  164.    errno = ESTUPID; /* it didn't arrive. */
  165.    return -1;
  166.   }
  167.  return acc[0];
  168. }
  169.  
  170. int comm_getfd(fdcomm)
  171. int fdcomm;
  172. {
  173.  int fd;
  174.  int tries;
  175.  
  176.  for (tries = 0;tries < 100;++tries)
  177.   {
  178.    fd = cgf(fdcomm);
  179.    if (fd != -1)
  180.      return fd;
  181.    gaargh(10000);
  182.   }
  183.  return -1;
  184. }
  185.