1 /*
2
3 $Header: socket.c[1.17] Wed Sep 9 16:23:14 1992 nickel@cs.tu-berlin.de proposed $
4 This file is part of socket(1).
5 Copyright (C) 1992 by Juergen Nickelsen <nickel@cs.tu-berlin.de>
6 Please read the file COPYRIGHT for further details.
7
8 */
9
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #ifdef USE_INET6
13 #include <sys/time.h>
14 #endif /* USE_INET6 */
15 #include <netinet/in.h>
16 #include <netdb.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #ifdef SEQUENT
20 #include <strings.h>
21 #else
22 #include <string.h>
23 #endif
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include "globals.h"
27
28 /* global variables */
29 int forkflag = 0 ; /* server forks on connection */
30 int serverflag = 0 ; /* create server socket */
31 int loopflag = 0 ; /* loop server */
32 int verboseflag = 0 ; /* give messages */
33 int readonlyflag = 0 ; /* only read from socket */
34 int writeonlyflag = 0 ; /* only write to socket */
35 int quitflag = 0 ; /* quit connection on EOF */
36 int crlfflag = 0 ; /* socket expects and delivers CRLF */
37 int backgflag = 0 ; /* put yourself in background */
38 int active_socket ; /* socket with connection */
39 char *progname ; /* name of the game */
40 char *pipe_program = NULL ; /* program to execute in two-way pipe */
41
42 #ifndef USE_INET6
43 void server A((int port, char *service_name)) ;
44 void client A((char *host, int port, char *service_name)) ;
45 #else /* USE_INET6 */
46 void server A((char *port)) ;
47 void client A((char *host, char *port)) ;
48 #endif /* USE_INET6 */
49
50 void handle_server_connection A((void)) ;
51 extern void init_signals A((void)) ;
52 extern void do_io A((void)) ;
53
main(argc,argv)54 int main(argc, argv)
55 int argc ;
56 char **argv ;
57 {
58 char *cp ; /* to point to '/' in argv[0] */
59 int opt ; /* option character */
60 int error = 0 ; /* usage error occurred */
61 extern int optind ; /* from getopt() */
62 /* char *host ; */ /* name of remote host */
63 #ifndef USE_INET6
64 int port ; /* port number for socket */
65 char *service_name ; /* name of service for port */
66 #endif /* USE_INET6 */
67
68 /* print version ID if requested */
69 if (argv[1] && !strcmp(argv[1], "-version")) {
70 puts(so_release()) ;
71 exit(0) ;
72 }
73
74 /* set up progname for later use */
75 progname = argv[0] ;
76 cp = strrchr(progname, '/');
77 if (cp) progname = cp + 1 ;
78
79 /* parse options */
80 while ((opt = getopt(argc, argv, "bcflp:qrsvw?")) != -1) {
81 switch (opt) {
82 case 'f':
83 forkflag = 1 ;
84 break ;
85 case 'c':
86 crlfflag = 1 ;
87 break ;
88 case 'w':
89 writeonlyflag = 1 ;
90 break ;
91 case 'p':
92 pipe_program = argv[optind - 1] ;
93 break ;
94 case 'q':
95 quitflag = 1 ;
96 break ;
97 case 'r':
98 readonlyflag = 1 ;
99 break ;
100 case 's':
101 serverflag = 1 ;
102 break ;
103 case 'v':
104 verboseflag = 1 ;
105 break ;
106 case 'l':
107 loopflag = 1 ;
108 break ;
109 case 'b':
110 backgflag = 1 ;
111 break ;
112 default:
113 error++ ;
114 }
115 }
116 if (error || /* usage error? */
117 argc - optind + serverflag != 2) { /* number of args ok? */
118 usage() ;
119 exit(15) ;
120 }
121
122 /* check some option combinations */
123 #define senseless(s1, s2) \
124 fprintf(stderr, "It does not make sense to set %s and %s.\n", (s1), (s2))
125
126 if (writeonlyflag && readonlyflag) {
127 senseless("-r", "-w") ;
128 exit(15) ;
129 }
130 if (loopflag && !serverflag) {
131 senseless("-l", "not -s") ;
132 exit(15) ;
133 }
134 if (backgflag && !serverflag) {
135 senseless("-b", "not -s") ;
136 exit(15) ;
137 }
138 if (forkflag && !serverflag) {
139 senseless("-f", "not -s") ;
140 }
141
142 /* set up signal handling */
143 init_signals() ;
144
145 #ifndef USE_INET6
146 /* get port number */
147 port = resolve_service(argv[optind + 1 - serverflag],
148 "tcp", &service_name) ;
149 if (port < 0) {
150 fprintf(stderr, "%s: unknown service\n", progname) ;
151 exit(5) ;
152 }
153
154 #endif /* not USE_INET6 */
155 /* and go */
156 if (serverflag) {
157 if (backgflag) {
158 background() ;
159 }
160 #ifndef USE_INET6
161 server(port, service_name) ;
162 #else /* USE_INET6 */
163 server(argv[optind]) ;
164 #endif /* USE_INET6 */
165 } else {
166 #ifndef USE_INET6
167 client(argv[optind], port, service_name) ;
168 #else /* USE_INET6 */
169 client(argv[optind], argv[optind + 1]) ;
170 #endif /* USE_INET6 */
171 }
172 exit(0) ;
173 }
174
175
176 #ifndef USE_INET6
server(port,service_name)177 void server(port, service_name)
178 int port ;
179 char *service_name ;
180 #else /* USE_INET6 */
181 void server(port)
182 char *port ;
183 #endif /* USE_INET6 */
184 {
185 #ifndef USE_INET6
186 int socket_handle, alen ;
187 #else /* USE_INET6 */
188 int *socket_handle_list ;
189 #endif /* USE_INET6 */
190
191 /* allocate server socket */
192 #ifndef USE_INET6
193 socket_handle = create_server_socket(port, 1) ;
194 if (socket_handle < 0) {
195 #else /* USE_INET6 */
196 socket_handle_list = create_server_sockets(&port, 1) ;
197 if (!socket_handle_list) {
198 #endif /* USE_INET6 */
199 perror2("server socket") ;
200 exit(1) ;
201 }
202 #ifdef USE_INET6
203
204 #endif /* USE_INET6 */
205 if (verboseflag) {
206 #ifndef USE_INET6
207 fprintf(stderr, "listening on port %d", port) ;
208 if (service_name) {
209 fprintf(stderr, " (%s)", service_name) ;
210 }
211 fprintf(stderr, "\n") ;
212 #else /* USE_INET6 */
213 char *ip, *port;
214 int fd, i;
215
216 fd = socket_handle_list[1];
217 for (i = 1; i <= socket_handle_list[0]; i++) {
218 if (!fd || fd < socket_handle_list[i])
219 fd = socket_handle_list[i];
220 socket_local_name (fd, NULL, &ip, &port);
221 fprintf(stderr, "listening at address %s on port %s\n", ip, port) ;
222 }
223 #endif /* USE_INET6 */
224 }
225
226 /* server loop */
227 do {
228 #ifndef USE_INET6
229 struct sockaddr_in sa ;
230
231 alen = sizeof(sa) ;
232
233 /* accept a connection */
234 if ((active_socket = accept(socket_handle,
235 (struct sockaddr *) &sa,
236 &alen)) == -1) {
237 perror2("accept") ;
238 } else {
239 /* if verbose, get name of peer and give message */
240 if (verboseflag) {
241 struct hostent *he ;
242 long norder ;
243 char dotted[20] ;
244
245 he = gethostbyaddr((const char *)&sa.sin_addr.s_addr,
246 sizeof(sa.sin_addr.s_addr), AF_INET) ;
247 if (!he) {
248 norder = htonl(sa.sin_addr.s_addr) ;
249 sprintf(dotted, "%d.%d.%d.%d",
250 (int)((norder >> 24) & 0xff),
251 (int)((norder >> 16) & 0xff),
252 (int)((norder >> 8) & 0xff),
253 (int)(norder & 0xff)) ;
254 #else /* USE_INET6 */
255 struct timeval tv;
256 fd_set readfd;
257 int fd, i, nfds, retval;
258
259 fd = socket_handle_list[1];
260 for (i = 1; i <= socket_handle_list[0]; i++) {
261 if (!fd || fd < socket_handle_list[i])
262 fd = socket_handle_list[i];
263 }
264 nfds=fd+1;
265
266 FD_ZERO(&readfd);
267 for (i = 1; i <= socket_handle_list[0]; i++)
268 FD_SET(socket_handle_list[i],&readfd);
269
270 tv.tv_sec = 10;
271 tv.tv_usec = 0;
272
273 retval = select(nfds, &readfd, NULL, NULL, &tv);
274
275 if(retval!=-1) {
276 for (i = 1; i <= socket_handle_list[0]; i++) {
277 fd = socket_handle_list[i];
278 if (FD_ISSET(fd, &readfd)) {
279
280 /* accept a connection */
281 active_socket = accept(fd, (struct sockaddr *) 0, (int *)0);
282 if (active_socket == -1) {
283 perror2("accept") ;
284 } else {
285 /* if verbose, get name of peer and give message */
286 if (verboseflag) {
287 char *host, *ip, *port;
288
289 if(!socket_remote_name(active_socket,&host, &ip, &port)) {
290 fprintf(stderr, "connection from %s at %s to %s\n", host, ip, port);
291 }
292 else
293 fprintf(stderr, "cannot get name or address of peer") ;
294 }
295
296 if (forkflag) {
297 switch (fork()) {
298 case 0:
299 handle_server_connection() ;
300 exit(0) ;
301 case -1:
302 perror2("fork") ;
303 break ;
304 default:
305 close(active_socket) ;
306 wait_for_children() ;
307 }
308 } else {
309 handle_server_connection() ;
310 }
311 }
312 #endif /* USE_INET6 */
313 }
314 #ifndef USE_INET6
315 fprintf(stderr, "connection from %s\n",
316 (he ? he->h_name : dotted)) ;
317 }
318 if (forkflag) {
319 switch (fork()) {
320 case 0:
321 handle_server_connection() ;
322 exit(0) ;
323 case -1:
324 perror2("fork") ;
325 break ;
326 default:
327 close(active_socket) ;
328 wait_for_children() ;
329 }
330 } else {
331 handle_server_connection() ;
332 #endif /* not USE_INET6 */
333 }
334 }
335 } while (loopflag) ;
336 #ifdef USE_INET6
337
338 free (socket_handle_list);
339 #endif /* USE_INET6 */
340 }
341
342
handle_server_connection()343 void handle_server_connection()
344 {
345 /* open pipes to program, if requested */
346 if (pipe_program != NULL) {
347 open_pipes(pipe_program) ;
348 }
349 /* enter IO loop */
350 do_io() ;
351 /* connection is closed now */
352 close(active_socket) ;
353 if (pipe_program) {
354 /* remove zombies */
355 wait_for_children() ;
356 }
357 }
358
359
360 #ifndef USE_INET6
client(host,port,service_name)361 void client(host, port, service_name)
362 #else /* USE_INET6 */
363 void client(host, port)
364 #endif /* USE_INET6 */
365 char *host ;
366 #ifndef USE_INET6
367 int port ;
368 char *service_name ;
369 #else /* USE_INET6 */
370 char *port ;
371 #endif /* USE_INET6 */
372 {
373 /* get connection */
374 #ifndef USE_INET6
375 active_socket = create_client_socket(&host, port) ;
376 #else /* USE_INET6 */
377 active_socket = create_client_socket(&host, &port) ;
378 #endif /* USE_INET6 */
379 if (active_socket == -1) {
380 perror2("client socket") ;
381 exit(errno) ;
382 } else if (active_socket == -2) {
383 fprintf(stderr, "%s: unknown host %s\n", progname, host) ;
384 exit(13) ;
385 }
386 if (verboseflag) {
387 #ifndef USE_INET6
388 fprintf(stderr, "connected to %s port %d", host, port) ;
389 if (service_name) {
390 fprintf(stderr, " (%s)", service_name) ;
391 }
392 fprintf(stderr, "\n") ;
393 #else /* USE_INET6 */
394 char *host, *ip, *port;
395
396 socket_local_name (active_socket, &host, &ip, &port);
397 fprintf(stderr, "connected to %s with address %s at port %s\n", host, ip, port) ;
398 #endif /* USE_INET6 */
399 }
400
401 /* open pipes to program if requested */
402 if (pipe_program != NULL) {
403 open_pipes(pipe_program) ;
404 }
405 /* enter IO loop */
406 do_io() ;
407 /* connection is closed now */
408 close(active_socket) ;
409 }
410
411 /*EOF*/
412