Introduction
Introduction Statistics Contact Development Disclaimer Help
announce.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
announce.c (2724B)
---
1 #include <u.h>
2 #define NOPLAN9DEFINES
3 #include <libc.h>
4
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <netinet/tcp.h>
8 #include <sys/un.h>
9 #include <errno.h>
10
11 #undef sun
12 #define sun sockun
13
14 int
15 _p9netfd(char *dir)
16 {
17 int fd;
18
19 if(strncmp(dir, "/dev/fd/", 8) != 0)
20 return -1;
21 fd = strtol(dir+8, &dir, 0);
22 if(*dir != 0)
23 return -1;
24 return fd;
25 }
26
27 static void
28 putfd(char *dir, int fd)
29 {
30 snprint(dir, NETPATHLEN, "/dev/fd/%d", fd);
31 }
32
33 #undef unix
34 #define unix sockunix
35
36 int
37 p9announce(char *addr, char *dir)
38 {
39 int proto;
40 char *buf, *unix;
41 char *net;
42 u32int host;
43 int port, s;
44 int n;
45 socklen_t sn;
46 struct sockaddr_in sa;
47 struct sockaddr_un sun;
48
49 buf = strdup(addr);
50 if(buf == nil)
51 return -1;
52
53 if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
54 free(buf);
55 return -1;
56 }
57 if(strcmp(net, "tcp") == 0)
58 proto = SOCK_STREAM;
59 else if(strcmp(net, "udp") == 0)
60 proto = SOCK_DGRAM;
61 else if(strcmp(net, "unix") == 0)
62 goto Unix;
63 else{
64 werrstr("can only handle tcp, udp, and unix: not %s", ne…
65 free(buf);
66 return -1;
67 }
68 free(buf);
69
70 memset(&sa, 0, sizeof sa);
71 memmove(&sa.sin_addr, &host, 4);
72 sa.sin_family = AF_INET;
73 sa.sin_port = htons(port);
74 if((s = socket(AF_INET, proto, 0)) < 0)
75 return -1;
76 sn = sizeof n;
77 if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >=…
78 && n == SOCK_STREAM){
79 n = 1;
80 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeo…
81 }
82 if(bind(s, (struct sockaddr*)&sa, sizeof sa) < 0){
83 close(s);
84 return -1;
85 }
86 if(proto == SOCK_STREAM){
87 listen(s, 8);
88 putfd(dir, s);
89 }
90 return s;
91
92 Unix:
93 memset(&sun, 0, sizeof sun);
94 sun.sun_family = AF_UNIX;
95 strcpy(sun.sun_path, unix);
96 if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
97 return -1;
98 sn = sizeof sun;
99 if(bind(s, (struct sockaddr*)&sun, sizeof sun) < 0){
100 if(errno == EADDRINUSE
101 && connect(s, (struct sockaddr*)&sun, sizeof sun) < 0
102 && errno == ECONNREFUSED){
103 /* dead socket, so remove it */
104 remove(unix);
105 close(s);
106 if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
107 return -1;
108 if(bind(s, (struct sockaddr*)&sun, sizeof sun) >…
109 goto Success;
110 }
111 close(s);
112 return -1;
113 }
114 Success:
115 listen(s, 8);
116 putfd(dir, s);
117 return s;
118 }
119
120 int
121 p9listen(char *dir, char *newdir)
122 {
123 int fd, one;
124
125 if((fd = _p9netfd(dir)) < 0){
126 werrstr("bad 'directory' in listen: %s", dir);
127 return -1;
128 }
129
130 if((fd = accept(fd, nil, nil)) < 0)
131 return -1;
132
133 one = 1;
134 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one…
135
136 putfd(newdir, fd);
137 return fd;
138 }
139
140 int
141 p9accept(int cfd, char *dir)
142 {
143 int fd;
144
145 if((fd = _p9netfd(dir)) < 0){
146 werrstr("bad 'directory' in accept");
147 return -1;
148 }
149 /* need to dup because the listen fd will be closed */
150 return dup(fd);
151 }
152
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.