1 /************************************************************************
2 * *
3 * Copyright 1988, 1989, 1990, Brown University, Providence, RI. *
4 * Permission to use, copy, modify and distribute this software and *
5 * its documentation for any purpose other than its incorporation *
6 * into a commercial product, is hereby granted, provided that this *
7 * copyright notice appears on all copies and the distribution is *
8 * only within the organization represented by the person receiving *
9 * the software from Brown. Brown requests notification of the of *
10 * any important modifications to this software or its documentation. *
11 * *
12 ************************************************************************/
13 /************************************************************************
14 * *
15 * socket.c *
16 * *
17 * All socket setup and io system calls are done here. *
18 * *
19 ************************************************************************/
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <netinet/in.h>
24 #include <netinet/tcp.h>
25 #include <arpa/inet.h>
26 #include <netdb.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <errno.h>
30
31 #ifdef __SVR4
32 #include <sys/file.h>
33 #endif
34
35 #include "xmx.h"
36
37 #define X_UNIX_DIR "/tmp/.X11-unix"
38 #define X_UNIX_PATH "/tmp/.X11-unix/X"
39 #define X_TCP_PORT 6000
40
41 /************************************************************************
42 * *
43 * server_sockets *
44 * *
45 * Create X server style sockets, bind to well known addresses *
46 * and listen on them. Returns the number of sockets or -1 if *
47 * an error occurs. Fdsp is pointed to a static array of the *
48 * descriptors. *
49 * *
50 ************************************************************************/
51 int
server_sockets(display,fdsp)52 server_sockets(display, fdsp)
53 int display;
54 int **fdsp;
55 {
56 register i;
57 int s, oumask;
58 struct linger linger;
59 static int fds[2]; /* return array */
60 static struct sockaddr_un usock;
61 static struct sockaddr_in isock;
62
63 /* create UNIX domain socket */
64 usock.sun_family = AF_UNIX;
65 (void)sprintf(usock.sun_path, "%s%d", X_UNIX_PATH, display);
66 oumask = umask(0);
67 (void)mkdir(X_UNIX_DIR, 0777);
68 (void)umask(oumask);
69 (void)unlink(usock.sun_path);
70 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
71 return perr(-1, usock.sun_path);
72
73 i = strlen(usock.sun_path) + sizeof(usock.sun_family);
74 if (bind(s, (struct sockaddr *)&usock, i))
75 return perr(-1, usock.sun_path);
76
77 if (listen(s, 5))
78 return perr(-1, usock.sun_path);
79
80 fds[0] = s;
81 /* create TCP socket */
82 isock.sin_family = AF_INET;
83 isock.sin_port = htons((u_short)(X_TCP_PORT + display));
84 isock.sin_addr.s_addr = htonl(INADDR_ANY);
85 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
86 return perr(-1, "tcp socket");
87
88 for (i=20; i && bind(s, (struct sockaddr *)&isock, sizeof(isock)); i--)
89 sleep(10);
90 if (i == 0)
91 return perr(-1, "tcp socket");
92
93 linger.l_onoff = 0;
94 linger.l_linger = 0;
95 if (setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger)))
96 return perr(-1, "tcp socket");
97
98 if (listen(s, 5))
99 return perr(-1, "tcp socket");
100
101 fds[1] = s;
102
103 *fdsp = fds;
104 return 2;
105 }
106
107 /************************************************************************
108 * *
109 * accept_client *
110 * *
111 * Accept a pending connection from a client. Returns the new *
112 * socket file descriptor or -1 if an error occurred. *
113 * *
114 ************************************************************************/
115 int
accept_client(s)116 accept_client(s)
117 int s;
118 {
119 int i;
120 int ns;
121 int addrlen;
122 struct sockaddr addr;
123
124 addrlen = sizeof(addr);
125 if ((ns = accept(s, &addr, &addrlen)) < 0)
126 return perr(-1, "accept");
127
128 if (addr.sa_family == AF_INET) {
129 i = 1;
130 if (setsockopt(ns, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)))
131 return perr(-1, "client socket");
132 }
133 (void)fcntl(ns, F_SETFL, FNDELAY);
134
135 return ns;
136 }
137
138 /************************************************************************
139 * *
140 * client_socket *
141 * *
142 * Connect to an X server. Returns the socket file descriptor or *
143 * -1 if an error occurred. *
144 * *
145 ************************************************************************/
146 int
client_socket(hostname,display,bfactor)147 client_socket(hostname, display, bfactor)
148 char *hostname;
149 int display;
150 int bfactor;
151 {
152 register len;
153 int s;
154 int sendbufopt, sendbuflen;
155 unsigned long iaddr;
156 struct hostent *h;
157 struct sockaddr *sock;
158 static struct sockaddr_un usock;
159 static struct sockaddr_in isock;
160
161 /* UNIX domain socket */
162 if (*hostname == '\0' || strcmp(hostname, "unix") == 0) {
163 usock.sun_family = AF_UNIX;
164 sprintf(usock.sun_path, "%s%d", X_UNIX_PATH, display);
165 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
166 return perr(-1, usock.sun_path);
167
168 sock = (struct sockaddr *)&usock;
169 len = sizeof(usock);
170 }
171 else { /* TCP socket */
172 isock.sin_family = AF_INET;
173 isock.sin_port = htons((u_short)(X_TCP_PORT + display));
174 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
175 return perr(-1, "tcp socket");
176
177 if ((long)(iaddr = inet_addr(hostname)) < 0) {
178 if ((h = gethostbyname(hostname)) == 0)
179 return err(-1, "%s: host not found\n", hostname);
180
181 if (h->h_addrtype != AF_INET)
182 return err(-1, "%s: not an internet host\n", hostname);
183
184 bcopy((char *)*h->h_addr_list,(char *)&isock.sin_addr,h->h_length);
185 }
186 else
187 isock.sin_addr.s_addr = iaddr;
188 sock = (struct sockaddr *)&isock;
189 len = sizeof(isock);
190 }
191 #ifdef SO_SNDBUF
192 if (bfactor > 1) {
193 sendbuflen = sizeof(sendbufopt);
194 if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sendbufopt, &sendbuflen))
195 perror("getsockopt[SNDBUF]");
196 else {
197 sendbufopt *= bfactor;
198 /*
199 warn("client_socket: changing sndbuf size to %d\n",sendbufopt);
200 */
201 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sendbufopt, sendbuflen))
202 perror("getsockopt[SNDBUF]");
203 }
204 }
205 #endif
206 if (connect(s, sock, len) < 0) {
207 perror("connect");
208 (void)close(s);
209 return -1;
210 }
211 (void)fcntl(s, F_SETFL, FNDELAY);
212
213 return s;
214 }
215