Introduction
Introduction Statistics Contact Development Disclaimer Help
dial.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
dial.c (2943B)
---
1 #include <u.h>
2 #include <libc.h>
3
4 #undef accept
5 #undef announce
6 #undef dial
7 #undef setnetmtpt
8 #undef hangup
9 #undef listen
10 #undef netmkaddr
11 #undef reject
12
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <netinet/tcp.h>
16 #include <sys/un.h>
17 #include <netdb.h>
18
19 #undef unix
20 #define unix xunix
21
22 int
23 p9dial(char *addr, char *local, char *dummy2, int *dummy3)
24 {
25 char *buf;
26 char *net, *unix;
27 u32int host;
28 int port;
29 int proto;
30 socklen_t sn;
31 int n;
32 struct sockaddr_in sa, sal;
33 struct sockaddr_un su;
34 int s;
35
36 if(dummy2 || dummy3){
37 werrstr("cannot handle extra arguments in dial");
38 return -1;
39 }
40
41 buf = strdup(addr);
42 if(buf == nil)
43 return -1;
44
45 if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
46 free(buf);
47 return -1;
48 }
49 if(strcmp(net, "unix") != 0 && host == 0){
50 werrstr("invalid dial address 0.0.0.0 (aka *)");
51 free(buf);
52 return -1;
53 }
54
55 if(strcmp(net, "tcp") == 0)
56 proto = SOCK_STREAM;
57 else if(strcmp(net, "udp") == 0)
58 proto = SOCK_DGRAM;
59 else if(strcmp(net, "unix") == 0)
60 goto Unix;
61 else{
62 werrstr("can only handle tcp, udp, and unix: not %s", ne…
63 free(buf);
64 return -1;
65 }
66 free(buf);
67
68 if((s = socket(AF_INET, proto, 0)) < 0)
69 return -1;
70
71 if(local){
72 buf = strdup(local);
73 if(buf == nil){
74 close(s);
75 return -1;
76 }
77 if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
78 badlocal:
79 free(buf);
80 close(s);
81 return -1;
82 }
83 if(unix){
84 werrstr("bad local address %s for dial %s", loca…
85 goto badlocal;
86 }
87 memset(&sal, 0, sizeof sal);
88 memmove(&sal.sin_addr, &local, 4);
89 sal.sin_family = AF_INET;
90 sal.sin_port = htons(port);
91 sn = sizeof n;
92 if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n,…
93 && n == SOCK_STREAM){
94 n = 1;
95 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&…
96 }
97 if(bind(s, (struct sockaddr*)&sal, sizeof sal) < 0)
98 goto badlocal;
99 free(buf);
100 }
101
102 n = 1;
103 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof n);
104 if(host != 0){
105 memset(&sa, 0, sizeof sa);
106 memmove(&sa.sin_addr, &host, 4);
107 sa.sin_family = AF_INET;
108 sa.sin_port = htons(port);
109 if(connect(s, (struct sockaddr*)&sa, sizeof sa) < 0){
110 close(s);
111 return -1;
112 }
113 }
114 if(proto == SOCK_STREAM){
115 int one = 1;
116 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&one, siz…
117 }
118 return s;
119
120 Unix:
121 if(local){
122 werrstr("local address not supported on unix network");
123 free(buf);
124 return -1;
125 }
126 /* Allow regular files in addition to Unix sockets. */
127 if((s = open(unix, ORDWR)) >= 0)
128 return s;
129 memset(&su, 0, sizeof su);
130 su.sun_family = AF_UNIX;
131 if(strlen(unix)+1 > sizeof su.sun_path){
132 werrstr("unix socket name too long");
133 free(buf);
134 return -1;
135 }
136 strcpy(su.sun_path, unix);
137 free(buf);
138 if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
139 werrstr("socket: %r");
140 return -1;
141 }
142 if(connect(s, (struct sockaddr*)&su, sizeof su) < 0){
143 werrstr("connect %s: %r", su.sun_path);
144 close(s);
145 return -1;
146 }
147 return s;
148 }
149
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.