aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--trace-cmd.c196
-rw-r--r--trace-listen.c450
-rw-r--r--trace-local.h2
4 files changed, 639 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 08f488c..481b1a7 100644
--- a/Makefile
+++ b/Makefile
@@ -140,7 +140,7 @@ endef
140 $(Q)$(call check_gui) 140 $(Q)$(call check_gui)
141 141
142 142
143TRACE_CMD_OBJS = trace-cmd.o trace-read.o trace-split.o 143TRACE_CMD_OBJS = trace-cmd.o trace-read.o trace-split.o trace-listen.o
144TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o trace-compat.o \ 144TRACE_VIEW_OBJS = trace-view.o trace-view-store.o trace-filter.o trace-compat.o \
145 trace-hash.o 145 trace-hash.o
146TRACE_GRAPH_OBJS = trace-graph.o trace-compat.o trace-hash.o trace-filter.o \ 146TRACE_GRAPH_OBJS = trace-graph.o trace-compat.o trace-hash.o trace-filter.o \
diff --git a/trace-cmd.c b/trace-cmd.c
index e89362d..cdd78f4 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -27,6 +27,8 @@
27#include <sys/types.h> 27#include <sys/types.h>
28#include <sys/stat.h> 28#include <sys/stat.h>
29#include <sys/wait.h> 29#include <sys/wait.h>
30#include <sys/socket.h>
31#include <netdb.h>
30#include <pthread.h> 32#include <pthread.h>
31#include <fcntl.h> 33#include <fcntl.h>
32#include <unistd.h> 34#include <unistd.h>
@@ -48,7 +50,7 @@
48#define ITER_CTRL "trace_options" 50#define ITER_CTRL "trace_options"
49#define MAX_LATENCY "tracing_max_latency" 51#define MAX_LATENCY "tracing_max_latency"
50 52
51unsigned int page_size; 53static unsigned int page_size;
52 54
53static const char *output_file = "trace.dat"; 55static const char *output_file = "trace.dat";
54 56
@@ -57,6 +59,10 @@ static int sleep_time = 1000;
57static int cpu_count; 59static int cpu_count;
58static int *pids; 60static int *pids;
59 61
62static char *host;
63static int *client_ports;
64static int sfd;
65
60static int filter_task; 66static int filter_task;
61static int filter_pid = -1; 67static int filter_pid = -1;
62 68
@@ -116,7 +122,7 @@ static void kill_threads(void)
116{ 122{
117 int i; 123 int i;
118 124
119 if (!cpu_count) 125 if (!cpu_count || !pids)
120 return; 126 return;
121 127
122 for (i = 0; i < cpu_count; i++) { 128 for (i = 0; i < cpu_count; i++) {
@@ -895,6 +901,41 @@ static void flush(int sig)
895 tracecmd_stop_recording(recorder); 901 tracecmd_stop_recording(recorder);
896} 902}
897 903
904static void connect_port(int cpu)
905{
906 struct addrinfo hints;
907 struct addrinfo *results, *rp;
908 int s;
909 char buf[BUFSIZ];
910
911 snprintf(buf, BUFSIZ, "%d", client_ports[cpu]);
912
913 memset(&hints, 0, sizeof(hints));
914 hints.ai_family = AF_UNSPEC;
915 hints.ai_socktype = SOCK_DGRAM;
916
917 s = getaddrinfo(host, buf, &hints, &results);
918 if (s != 0)
919 die("connecting to UDP server %s:%s", host, buf);
920
921 for (rp = results; rp != NULL; rp = rp->ai_next) {
922 sfd = socket(rp->ai_family, rp->ai_socktype,
923 rp->ai_protocol);
924 if (sfd == -1)
925 continue;
926 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != 1)
927 break;
928 close(sfd);
929 }
930
931 if (rp == NULL)
932 die("Can not connect to UDP server %s:%s", host, buf);
933
934 freeaddrinfo(results);
935
936 client_ports[cpu] = sfd;
937}
938
898static int create_recorder(int cpu) 939static int create_recorder(int cpu)
899{ 940{
900 char *file; 941 char *file;
@@ -913,10 +954,14 @@ static int create_recorder(int cpu)
913 /* do not kill tasks on error */ 954 /* do not kill tasks on error */
914 cpu_count = 0; 955 cpu_count = 0;
915 956
916 file = get_temp_file(cpu); 957 if (client_ports) {
917 958 connect_port(cpu);
918 recorder = tracecmd_create_recorder(file, cpu); 959 recorder = tracecmd_create_recorder_fd(client_ports[cpu], cpu);
919 put_temp_file(file); 960 } else {
961 file = get_temp_file(cpu);
962 recorder = tracecmd_create_recorder(file, cpu);
963 put_temp_file(file);
964 }
920 965
921 if (!recorder) 966 if (!recorder)
922 die ("can't create recorder"); 967 die ("can't create recorder");
@@ -927,18 +972,125 @@ static int create_recorder(int cpu)
927 exit(0); 972 exit(0);
928} 973}
929 974
975static void setup_network(void)
976{
977 struct tracecmd_output *handle;
978 struct addrinfo hints;
979 struct addrinfo *result, *rp;
980 int sfd, s;
981 ssize_t n;
982 char buf[BUFSIZ];
983 char *server;
984 char *port;
985 char *p;
986 int cpu;
987 int i;
988
989 if (!strchr(host, ':')) {
990 server = strdup("localhost");
991 if (!server)
992 die("alloctating server");
993 port = host;
994 host = server;
995 } else {
996 host = strdup(host);
997 if (!host)
998 die("alloctating server");
999 server = strtok_r(host, ":", &p);
1000 port = strtok_r(NULL, ":", &p);
1001 }
1002
1003 memset(&hints, 0, sizeof(hints));
1004 hints.ai_family = AF_UNSPEC;
1005 hints.ai_socktype = SOCK_STREAM;
1006
1007 s = getaddrinfo(server, port, &hints, &result);
1008 if (s != 0)
1009 die("getaddrinfo: %s", gai_strerror(s));
1010
1011 for (rp = result; rp != NULL; rp = rp->ai_next) {
1012 sfd = socket(rp->ai_family, rp->ai_socktype,
1013 rp->ai_protocol);
1014 if (sfd == -1)
1015 continue;
1016
1017 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
1018 break;
1019 close(sfd);
1020 }
1021
1022 if (!rp)
1023 die("Can not connect to %s:%d", server, port);
1024
1025 freeaddrinfo(result);
1026
1027 n = read(sfd, buf, 8);
1028
1029 /* Make sure the server is the tracecmd server */
1030 if (memcmp(buf, "tracecmd", 8) != 0)
1031 die("server not tracecmd server");
1032
1033 /* write the number of CPUs we have (in ASCII) */
1034
1035 sprintf(buf, "%d", cpu_count);
1036
1037 /* include \0 */
1038 write(sfd, buf, strlen(buf)+1);
1039
1040 /* write the pagesize (in ASCII) */
1041
1042 page_size = getpagesize();
1043 sprintf(buf, "%d", page_size);
1044
1045 /* include \0 */
1046 write(sfd, buf, strlen(buf)+1);
1047
1048 client_ports = malloc_or_die(sizeof(int) * cpu_count);
1049
1050 /*
1051 * Now we will receive back a comma deliminated list
1052 * of client ports to connect to.
1053 */
1054 for (cpu = 0; cpu < cpu_count; cpu++) {
1055 for (i = 0; i < BUFSIZ; i++) {
1056 n = read(sfd, buf+i, 1);
1057 if (n != 1)
1058 die("Error, reading server ports");
1059 if (!buf[i] || buf[i] == ',')
1060 break;
1061 }
1062 if (i == BUFSIZ)
1063 die("read bad port number");
1064 buf[i] = 0;
1065 client_ports[cpu] = atoi(buf);
1066 }
1067
1068 /* Now create the handle through this socket */
1069 handle = tracecmd_create_init_fd(sfd, cpu_count);
1070
1071 /* OK, we are all set, let'r rip! */
1072}
1073
1074static void finish_network(void)
1075{
1076 close(sfd);
1077 free(host);
1078}
1079
930static void start_threads(void) 1080static void start_threads(void)
931{ 1081{
932 int i; 1082 int i;
933 1083
934 cpu_count = count_cpus(); 1084 cpu_count = count_cpus();
935 1085
1086 if (host)
1087 setup_network();
1088
936 /* make a thread for every CPU we have */ 1089 /* make a thread for every CPU we have */
937 pids = malloc_or_die(sizeof(*pids) * cpu_count); 1090 pids = malloc_or_die(sizeof(*pids) * cpu_count);
938 1091
939 memset(pids, 0, sizeof(*pids) * cpu_count); 1092 memset(pids, 0, sizeof(*pids) * cpu_count);
940 1093
941
942 for (i = 0; i < cpu_count; i++) { 1094 for (i = 0; i < cpu_count; i++) {
943 pids[i] = create_recorder(i); 1095 pids[i] = create_recorder(i);
944 } 1096 }
@@ -950,6 +1102,11 @@ static void record_data(void)
950 char **temp_files; 1102 char **temp_files;
951 int i; 1103 int i;
952 1104
1105 if (host) {
1106 finish_network();
1107 return;
1108 }
1109
953 if (latency) 1110 if (latency)
954 handle = tracecmd_create_file_latency(output_file, cpu_count); 1111 handle = tracecmd_create_file_latency(output_file, cpu_count);
955 else { 1112 else {
@@ -1066,7 +1223,7 @@ void usage(char **argv)
1066 "usage:\n" 1223 "usage:\n"
1067 " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file] \\\n" 1224 " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file] \\\n"
1068 " [-s usecs][-O option ][-l func][-g func][-n func]\n" 1225 " [-s usecs][-O option ][-l func][-g func][-n func]\n"
1069 " [-P pid][command ...]\n" 1226 " [-P pid][-N host:port][command ...]\n"
1070 " -e run command with event enabled\n" 1227 " -e run command with event enabled\n"
1071 " -f filter for previous -e event\n" 1228 " -f filter for previous -e event\n"
1072 " -p run command with plugin enabled\n" 1229 " -p run command with plugin enabled\n"
@@ -1080,6 +1237,7 @@ void usage(char **argv)
1080 " -o data output file [default trace.dat]\n" 1237 " -o data output file [default trace.dat]\n"
1081 " -O option to enable (or disable)\n" 1238 " -O option to enable (or disable)\n"
1082 " -s sleep interval between recording (in usecs) [default: 1000]\n" 1239 " -s sleep interval between recording (in usecs) [default: 1000]\n"
1240 " -N host:port to connect to (see listen)\n"
1083 "\n" 1241 "\n"
1084 " %s start [-e event][-p plugin][-d][-O option ][-P pid]\n" 1242 " %s start [-e event][-p plugin][-d][-O option ][-P pid]\n"
1085 " Uses same options as record, but does not run a command.\n" 1243 " Uses same options as record, but does not run a command.\n"
@@ -1122,11 +1280,17 @@ void usage(char **argv)
1122 " if left out, will start at beginning of file\n" 1280 " if left out, will start at beginning of file\n"
1123 " end - decimal end time in seconds\n" 1281 " end - decimal end time in seconds\n"
1124 "\n" 1282 "\n"
1283 " %s listen -p port[-D][-o file][-d dir]\n"
1284 " Creates a socket to listen for clients.\n"
1285 " -D create it in daemon mode.\n"
1286 " -o file name to use for clients.\n"
1287 " -d diretory to store client files.\n"
1288 "\n"
1125 " %s list [-e][-p]\n" 1289 " %s list [-e][-p]\n"
1126 " -e list available events\n" 1290 " -e list available events\n"
1127 " -p list available plugins\n" 1291 " -p list available plugins\n"
1128 " -o list available options\n" 1292 " -o list available options\n"
1129 "\n", p, VERSION_STRING, p, p, p, p, p, p, p, p); 1293 "\n", p, VERSION_STRING, p, p, p, p, p, p, p, p, p);
1130 exit(-1); 1294 exit(-1);
1131} 1295}
1132 1296
@@ -1159,6 +1323,9 @@ int main (int argc, char **argv)
1159 if (strcmp(argv[1], "report") == 0) { 1323 if (strcmp(argv[1], "report") == 0) {
1160 trace_report(argc, argv); 1324 trace_report(argc, argv);
1161 exit(0); 1325 exit(0);
1326 } else if (strcmp(argv[1], "listen") == 0) {
1327 trace_listen(argc, argv);
1328 exit(0);
1162 } else if (strcmp(argv[1], "split") == 0) { 1329 } else if (strcmp(argv[1], "split") == 0) {
1163 trace_split(argc, argv); 1330 trace_split(argc, argv);
1164 exit(0); 1331 exit(0);
@@ -1166,7 +1333,7 @@ int main (int argc, char **argv)
1166 (strcmp(argv[1], "start") == 0) || 1333 (strcmp(argv[1], "start") == 0) ||
1167 ((extract = strcmp(argv[1], "extract") == 0))) { 1334 ((extract = strcmp(argv[1], "extract") == 0))) {
1168 1335
1169 while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:vg:l:n:P:")) >= 0) { 1336 while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:vg:l:n:P:N:")) >= 0) {
1170 switch (c) { 1337 switch (c) {
1171 case 'h': 1338 case 'h':
1172 usage(argv); 1339 usage(argv);
@@ -1241,6 +1408,8 @@ int main (int argc, char **argv)
1241 disable = 1; 1408 disable = 1;
1242 break; 1409 break;
1243 case 'o': 1410 case 'o':
1411 if (host)
1412 die("-o incompatible with -N");
1244 if (!record && !extract) 1413 if (!record && !extract)
1245 die("start does not take output\n" 1414 die("start does not take output\n"
1246 "Did you mean 'record'?"); 1415 "Did you mean 'record'?");
@@ -1257,6 +1426,13 @@ int main (int argc, char **argv)
1257 usage(argv); 1426 usage(argv);
1258 sleep_time = atoi(optarg); 1427 sleep_time = atoi(optarg);
1259 break; 1428 break;
1429 case 'N':
1430 if (!record)
1431 die("-N only available with record");
1432 if (output)
1433 die("-N incompatible with -o");
1434 host = optarg;
1435 break;
1260 } 1436 }
1261 } 1437 }
1262 1438
diff --git a/trace-listen.c b/trace-listen.c
new file mode 100644
index 0000000..d1314a5
--- /dev/null
+++ b/trace-listen.c
@@ -0,0 +1,450 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#define _LARGEFILE64_SOURCE
22#define _GNU_SOURCE
23#include <dirent.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <getopt.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netdb.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <signal.h>
34#include <errno.h>
35
36#include "trace-local.h"
37
38static char *default_output_dir = ".";
39static char *output_dir;
40static char *default_output_file = "trace";
41static char *output_file;
42
43static int backlog = 5;
44
45#define TEMP_FILE_STR "%s.%s:%s.cpu%d", output_file, host, port, cpu
46static char *get_temp_file(const char *host, const char *port, int cpu)
47{
48 char *file = NULL;
49 int size;
50
51 size = snprintf(file, 0, TEMP_FILE_STR);
52 file = malloc_or_die(size + 1);
53 sprintf(file, TEMP_FILE_STR);
54
55 return file;
56}
57
58static void put_temp_file(char *file)
59{
60 free(file);
61}
62
63#define MAX_PATH 1024
64
65static void delete_temp_file(const char *host, const char *port, int cpu)
66{
67 char file[MAX_PATH];
68
69 snprintf(file, MAX_PATH, TEMP_FILE_STR);
70 unlink(file);
71}
72
73static int read_string(int fd, char *buf, size_t size)
74{
75 size_t i;
76 int n;
77
78 for (i = 0; i < size; i++) {
79 n = read(fd, buf+i, 1);
80 if (!buf[i] || n <= 0)
81 break;
82 }
83
84 return i;
85}
86
87static int done;
88static void finish(int sig)
89{
90 done = 1;
91}
92
93static void process_udp_child(int sfd, const char *host, const char *port,
94 int cpu, int page_size)
95{
96 struct sockaddr_storage peer_addr;
97 socklen_t peer_addr_len;
98 char buf[page_size];
99 char *tempfile;
100 int fd;
101 int n;
102 int once = 0;
103
104 signal(SIGUSR1, finish);
105
106 tempfile = get_temp_file(host, port, cpu);
107 fd = open(tempfile, O_WRONLY | O_TRUNC | O_CREAT, 0644);
108 if (fd < 0)
109 die("creating %s", tempfile);
110
111 do {
112 peer_addr_len = sizeof(peer_addr);
113 /* TODO, make this copyless! */
114 n = read(sfd, buf, page_size);
115#if 0
116 n = recvfrom(sfd, buf, page_size, 0,
117 (struct sockaddr *)&peer_addr, &peer_addr_len);
118#endif
119 if (!n)
120 break;
121 if (n < page_size && !once) {
122 once = 1;
123 warning("read %d bytes, expected %d", n, page_size);
124 }
125 write(fd, buf, n);
126 } while (!done);
127
128 put_temp_file(tempfile);
129 exit(0);
130}
131
132#define START_PORT_SEARCH 1500
133#define MAX_PORT_SEARCH 6000
134
135static int open_udp(const char *node, const char *port, int *pid,
136 int cpu, int pagesize)
137{
138 struct addrinfo hints;
139 struct addrinfo *result, *rp;
140 int sfd, s;
141 char buf[BUFSIZ];
142 int num_port = START_PORT_SEARCH;
143
144 again:
145 snprintf(buf, BUFSIZ, "%d", num_port);
146
147 memset(&hints, 0, sizeof(hints));
148 hints.ai_family = AF_UNSPEC;
149 hints.ai_socktype = SOCK_DGRAM;
150 hints.ai_flags = AI_PASSIVE;
151
152 s = getaddrinfo(NULL, buf, &hints, &result);
153 if (s != 0)
154 die("getaddrinfo: error opening udp socket");
155
156 for (rp = result; rp != NULL; rp = rp->ai_next) {
157 sfd = socket(rp->ai_family, rp->ai_socktype,
158 rp->ai_protocol);
159 if (sfd < 0)
160 continue;
161
162 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
163 break;
164
165 close(sfd);
166 }
167
168 if (rp == NULL) {
169 freeaddrinfo(result);
170 if (++num_port > MAX_PORT_SEARCH)
171 die("No available ports to bind");
172 goto again;
173 }
174
175 freeaddrinfo(result);
176
177 *pid = fork();
178
179 if (*pid < 0)
180 die("creating udp reader");
181
182 if (!*pid)
183 process_udp_child(sfd, node, port, cpu, pagesize);
184
185 close(sfd);
186
187 return num_port;
188}
189
190static void process_client(const char *node, const char *port, int fd)
191{
192 char **temp_files;
193 char buf[BUFSIZ];
194 int *port_array;
195 int *pid_array;
196 int pagesize;
197 int udp_port;
198 int cpus;
199 int cpu;
200 int pid;
201 int ofd;
202 int n, s, t;
203
204 /* Let the client know what we are */
205 write(fd, "tracecmd", 8);
206
207 /* read back the CPU count */
208 n = read_string(fd, buf, BUFSIZ);
209 if (n == BUFSIZ)
210 /** ERROR **/
211 return;
212
213 cpus = atoi(buf);
214
215 printf("cpus=%d\n", cpus);
216 if (cpus < 0)
217 return;
218
219 /* next read the page size */
220 n = read_string(fd, buf, BUFSIZ);
221 if (n == BUFSIZ)
222 /** ERROR **/
223 return;
224
225 pagesize = atoi(buf);
226
227 printf("pagesize=%d\n", pagesize);
228 if (pagesize <= 0)
229 return;
230
231 /* Create the client file */
232 snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port);
233
234 ofd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0644);
235 if (ofd < 0)
236 die("Can not create file %s", buf);
237
238 port_array = malloc_or_die(sizeof(int) * cpus);
239 pid_array = malloc_or_die(sizeof(int) * cpus);
240 memset(pid_array, 0, sizeof(int) * cpus);
241
242 /* Now create a UDP port for each CPU */
243 for (cpu = 0; cpu < cpus; cpu++) {
244 udp_port = open_udp(node, port, &pid, cpu, pagesize);
245 if (udp_port < 0)
246 goto out_free;
247 port_array[cpu] = udp_port;
248 pid_array[cpu] = pid;
249 }
250
251 /* send the client a comma deliminated set of port numbers */
252 for (cpu = 0; cpu < cpus; cpu++) {
253 snprintf(buf, BUFSIZ, "%s%d",
254 cpu ? "," : "", port_array[cpu]);
255 write(fd, buf, strlen(buf));
256 }
257 /* end with null terminator */
258 write(fd, "\0", 1);
259
260 /* Now we are ready to start reading data from the client */
261 do {
262 n = read(fd, buf, BUFSIZ);
263 t = n;
264 s = 0;
265 do {
266 s = write(ofd, buf+s, t);
267 if (s < 0)
268 die("writing to file");
269 t -= s;
270 s = n - t;
271 } while (t);
272 } while (n > 0);
273
274 /* wait a little to let our readers finish reading */
275 sleep(1);
276
277 /* stop our readers */
278 for (cpu = 0; cpu < cpus; cpu++) {
279 if (pid_array[cpu] > 0)
280 kill(pid_array[cpu], SIGUSR1);
281 }
282
283 /* wait a little to have the readers clean up */
284 sleep(1);
285
286 /* Now put together the file */
287 temp_files = malloc_or_die(sizeof(*temp_files) * cpus);
288
289 for (cpu = 0; cpu < cpus; cpu++)
290 temp_files[cpu] = get_temp_file(node, port, cpu);
291
292 tracecmd_attach_cpu_data_fd(ofd, cpus, temp_files);
293
294 out_free:
295 for (cpu = 0; cpu < cpus; cpu++) {
296 if (pid_array[cpu] > 0) {
297 kill(pid_array[cpu], SIGKILL);
298 delete_temp_file(node, port, cpu);
299 pid_array[cpu] = 0;
300 }
301 }
302}
303
304static void do_listen(char *port)
305{
306 struct addrinfo hints;
307 struct addrinfo *result, *rp;
308 int sfd, s, cfd;
309 struct sockaddr_storage peer_addr;
310 socklen_t peer_addr_len;
311 ssize_t nread;
312 char buf[BUFSIZ];
313 char host[NI_MAXHOST], service[NI_MAXSERV];
314
315 memset(&hints, 0, sizeof(hints));
316 hints.ai_family = AF_UNSPEC;
317 hints.ai_socktype = SOCK_STREAM;
318 hints.ai_flags = AI_PASSIVE;
319
320 s = getaddrinfo(NULL, port, &hints, &result);
321 if (s != 0)
322 die("getaddrinfo: error opening %s", port);
323
324 for (rp = result; rp != NULL; rp = rp->ai_next) {
325 sfd = socket(rp->ai_family, rp->ai_socktype,
326 rp->ai_protocol);
327 if (sfd < 0)
328 continue;
329
330 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
331 break;
332
333 close(sfd);
334 }
335
336 if (rp == NULL)
337 die("Could not bind");
338
339 freeaddrinfo(result);
340
341 if (listen(sfd, backlog) < 0)
342 die("listen");
343
344 peer_addr_len = sizeof(peer_addr);
345
346 do {
347 cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len);
348 if (cfd < 0)
349 die("connecting");
350 s = getnameinfo((struct sockaddr *)&peer_addr, peer_addr_len,
351 host, NI_MAXHOST,
352 service, NI_MAXSERV, NI_NUMERICSERV);
353
354 if (s == 0)
355 printf("Connected with %s:%s\n",
356 host, service);
357 else {
358 printf("Error with getnameinfo: %s\n",
359 gai_strerror(s));
360 close(cfd);
361 close(sfd);
362 return;
363 }
364
365 process_client(host, service, cfd);
366
367 do {
368 if (nread > 0)
369 nread = read(cfd, buf, BUFSIZ);
370 if (cfd < 0)
371 die("client");
372 if (nread > 0)
373 write(1, buf, nread);
374 } while (nread);
375
376 close(cfd);
377 } while (0);
378}
379
380static void start_daemon(void)
381{
382}
383
384void trace_listen(int argc, char **argv)
385{
386 char *port = NULL;
387 char *iface;
388 int daemon = 0;
389 int c;
390
391 if (argc < 2)
392 usage(argv);
393
394 if (strcmp(argv[1], "listen") != 0)
395 usage(argv);
396
397 for (;;) {
398 int option_index = 0;
399 static struct option long_options[] = {
400 {"port", required_argument, NULL, 'p'},
401 {"help", no_argument, NULL, '?'},
402 {NULL, 0, NULL, 0}
403 };
404
405 c = getopt_long (argc-1, argv+1, "+hp:o:d:i:D",
406 long_options, &option_index);
407 if (c == -1)
408 break;
409 switch (c) {
410 case 'h':
411 usage(argv);
412 break;
413 case 'p':
414 port = optarg;
415 break;
416 case 'i':
417 iface = optarg;
418 break;
419 case 'd':
420 output_dir = optarg;
421 break;
422 case 'o':
423 output_file = optarg;
424 break;
425 case 'D':
426 daemon = 1;
427 default:
428 usage(argv);
429 }
430 }
431
432 if (!port)
433 usage(argv);
434
435 if ((argc - optind) >= 2)
436 usage(argv);
437
438 if (!output_file)
439 output_file = default_output_file;
440
441 if (!output_dir)
442 output_dir = default_output_dir;
443
444 if (daemon)
445 start_daemon();
446
447 do_listen(port);
448
449 return;
450}
diff --git a/trace-local.h b/trace-local.h
index 0e49fa4..4e44238 100644
--- a/trace-local.h
+++ b/trace-local.h
@@ -37,4 +37,6 @@ void trace_report(int argc, char **argv);
37 37
38void trace_split(int argc, char **argv); 38void trace_split(int argc, char **argv);
39 39
40void trace_listen(int argc, char **argv);
41
40#endif /* __TRACE_LOCAL_H */ 42#endif /* __TRACE_LOCAL_H */