git ssb

0+

cel / sslh



Tree: 9cc47a157d0302350ef9b12e141746ef7ef1da3b

Files: 9cc47a157d0302350ef9b12e141746ef7ef1da3b / echosrv.c

3902 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 int res;
98 char buffer[1 << 20];
99 int ret, prefix_len;
100
101 prefix_len = strlen(prefix);
102
103 memset(buffer, 0, sizeof(buffer));
104 strcpy(buffer, prefix);
105
106 while (1) {
107 ret = read(fd, buffer + prefix_len, sizeof(buffer));
108 if (ret == -1) {
109 fprintf(stderr, "%s", strerror(errno));
110 return;
111 }
112 res = write(fd, buffer, ret + prefix_len);
113 if (res < 0) {
114 fprintf(stderr, "%s", strerror(errno));
115 return;
116 }
117 }
118}
119
120void main_loop(int listen_sockets[], int num_addr_listen)
121{
122 int in_socket, i;
123
124 for (i = 0; i < num_addr_listen; i++) {
125 if (!fork()) {
126 while (1)
127 {
128 in_socket = accept(listen_sockets[i], 0, 0);
129 if (verbose) fprintf(stderr, "accepted fd %d\n", in_socket);
130
131 if (!fork())
132 {
133 close(listen_sockets[i]);
134 start_echo(in_socket);
135 exit(0);
136 }
137 close(in_socket);
138 }
139 }
140 }
141 wait(NULL);
142}
143
144int main(int argc, char *argv[])
145{
146
147 extern char *optarg;
148 extern int optind;
149 int num_addr_listen;
150
151 int *listen_sockets;
152
153 parse_cmdline(argc, argv);
154
155 num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen);
156
157 main_loop(listen_sockets, num_addr_listen);
158
159 return 0;
160}
161

Built with git-ssb-web