Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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