accept.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /* posix */
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <fcntl.h>
  7. #include <errno.h>
  8. #include <string.h>
  9. /* bsd extensions */
  10. #include <sys/uio.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <sys/un.h>
  14. #include "priv.h"
  15. int
  16. accept(int fd, void *a, int *alen)
  17. {
  18. int n, nfd, cfd;
  19. Rock *r, *nr;
  20. struct sockaddr_in *ip;
  21. char name[Ctlsize];
  22. char file[Ctlsize];
  23. char *p, *net;
  24. r = _sock_findrock(fd, 0);
  25. if(r == 0){
  26. errno = ENOTSOCK;
  27. return -1;
  28. }
  29. switch(r->domain){
  30. case PF_INET:
  31. switch(r->stype){
  32. case SOCK_DGRAM:
  33. net = "udp";
  34. break;
  35. case SOCK_STREAM:
  36. net = "tcp";
  37. break;
  38. }
  39. /* get control file name from listener process */
  40. n = read(fd, name, sizeof(name)-1);
  41. if(n <= 0){
  42. _syserrno();
  43. return -1;
  44. }
  45. name[n] = 0;
  46. cfd = open(name, O_RDWR);
  47. if(cfd < 0){
  48. _syserrno();
  49. return -1;
  50. }
  51. nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
  52. if(nfd < 0){
  53. _syserrno();
  54. return -1;
  55. }
  56. if(write(fd, "OK", 2) < 0){
  57. close(nfd);
  58. _syserrno();
  59. return -1;
  60. }
  61. /* get remote address */
  62. ip = (struct sockaddr_in*)&nr->raddr;
  63. _sock_ingetaddr(nr, ip, &n, "remote");
  64. if(a){
  65. memmove(a, ip, sizeof(struct sockaddr_in));
  66. *alen = sizeof(struct sockaddr_in);
  67. }
  68. return nfd;
  69. case PF_UNIX:
  70. if(r->other >= 0){
  71. errno = EGREG;
  72. return -1;
  73. }
  74. for(;;){
  75. /* read path to new connection */
  76. n = read(fd, name, sizeof(name) - 1);
  77. if(n < 0)
  78. return -1;
  79. if(n == 0)
  80. continue;
  81. name[n] = 0;
  82. /* open new connection */
  83. _sock_srvname(file, name);
  84. nfd = open(file, O_RDWR);
  85. if(nfd < 0)
  86. continue;
  87. /* confirm opening on new connection */
  88. if(write(nfd, name, strlen(name)) > 0)
  89. break;
  90. close(nfd);
  91. }
  92. nr = _sock_newrock(nfd);
  93. if(nr == 0){
  94. close(nfd);
  95. return -1;
  96. }
  97. nr->domain = r->domain;
  98. nr->stype = r->stype;
  99. nr->protocol = r->protocol;
  100. return nfd;
  101. default:
  102. errno = EOPNOTSUPP;
  103. return -1;
  104. }
  105. }