git ssb

0+

cel / sslh



Tree: 26b4bcd089f6c3a3c43d1380969c939e600b3ef2

Files: 26b4bcd089f6c3a3c43d1380969c939e600b3ef2 / echosrv.c

3972 bytesRaw
1/* echosrv: a simple line echo server with optional prefix adding.
2 *
3 * echsrv --listen localhost6:1234 --prefix "ssl: "
4 *
5 * This will bind to 1234, and echo every line pre-pending "ssl: ". This is
6 * used for testing: we create several such servers with different prefixes,
7 * then we connect test clients that can then check they get the proper data
8 * back (thus testing that shoveling works both ways) with the correct prefix
9 * (thus testing it connected to the expected service).
10 * **/
11
12#define _GNU_SOURCE
13#include <sys/types.h>
14#include <fcntl.h>
15#include <string.h>
16#include <unistd.h>
17#include <stdlib.h>
18#include <stdarg.h>
19#include <stdio.h>
20#include <signal.h>
21#include <sys/socket.h>
22#include <sys/wait.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
25#include <netdb.h>
26#include <pwd.h>
27#include <syslog.h>
28#include <libgen.h>
29#include <getopt.h>
30
31#include "common.h"
32
33/* Added to make the code compilable under CYGWIN
34 * */
35#ifndef SA_NOCLDWAIT
36#define SA_NOCLDWAIT 0
37#endif
38
39const char* USAGE_STRING =
40"echosrv\n" \
41"usage:\n" \
42"\techosrv [-v] --listen <address:port> [--prefix <prefix>]\n"
43"-v: verbose\n" \
44"--listen: address to listen on. Can be specified multiple times.\n" \
45"--prefix: add specified prefix before every line echoed.\n"
46"";
47
48const char* server_type = "echsrv"; /* keep setup_syslog happy */
49
50/*
51 * Settings that depend on the command line.
52 */
53char* prefix = "";
54int port;
55
56void parse_cmdline(int argc, char* argv[])
57{
58 int c;
59 struct option options[] = {
60 { "verbose", no_argument, &verbose, 1 },
61 { "numeric", no_argument, &numeric, 1 },
62 { "listen", required_argument, 0, 'l' },
63 { "prefix", required_argument, 0, 'p' },
64 };
65 struct addrinfo **a;
66
67 while ((c = getopt_long_only(argc, argv, "l:p:", options, NULL)) != -1) {
68 if (c == 0) continue;
69
70 switch (c) {
71
72 case 'l':
73 /* find the end of the listen list */
74 for (a = &addr_listen; *a; a = &((*a)->ai_next));
75 /* append the specified addresses */
76 resolve_name(a, optarg);
77 break;
78
79 case 'p':
80 prefix = optarg;
81 break;
82
83 default:
84 fprintf(stderr, "%s", USAGE_STRING);
85 exit(2);
86 }
87 }
88
89 if (!addr_listen) {
90 fprintf(stderr, "No listening port specified\n");
91 exit(1);
92 }
93}
94
95void start_echo(int fd)
96{
97 fd_set fds;
98 int res;
99 char buffer[1 << 20];
100 char* ret;
101 FILE *socket;
102
103 FD_ZERO(&fds);
104
105 socket = fdopen(fd, "r+");
106 if (!socket) {
107 CHECK_RES_DIE(-1, "fdopen");
108 }
109
110 while (1) {
111 ret = fgets(buffer, sizeof(buffer), socket);
112 if (!ret) {
113 fprintf(stderr, "%s", strerror(ferror(socket)));
114 return;
115 }
116 res = fprintf(socket, "%s%s", prefix, buffer);
117 if (res < 0) {
118 fprintf(stderr, "%s", strerror(ferror(socket)));
119 return;
120 }
121
122 fflush(socket);
123 }
124}
125
126void main_loop(int listen_sockets[], int num_addr_listen)
127{
128 int in_socket, i;
129
130 for (i = 0; i < num_addr_listen; i++) {
131 if (!fork()) {
132 while (1)
133 {
134 in_socket = accept(listen_sockets[i], 0, 0);
135 if (verbose) fprintf(stderr, "accepted fd %d\n", in_socket);
136
137 if (!fork())
138 {
139 close(listen_sockets[i]);
140 start_echo(in_socket);
141 exit(0);
142 }
143 close(in_socket);
144 }
145 }
146 }
147 wait(NULL);
148}
149
150int main(int argc, char *argv[])
151{
152
153 extern char *optarg;
154 extern int optind;
155 int num_addr_listen;
156
157 int *listen_sockets;
158
159 parse_cmdline(argc, argv);
160
161 num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen);
162
163 main_loop(listen_sockets, num_addr_listen);
164
165 return 0;
166}
167

Built with git-ssb-web