ust: improve message parsing
[ust.git] / libustcomm / ustcomm.c
CommitLineData
d0b5f2b9 1#define _GNU_SOURCE
f9e5ce61
PMF
2#include <sys/types.h>
3#include <signal.h>
4#include <errno.h>
5#include <sys/socket.h>
6#include <sys/un.h>
d0b5f2b9 7#include <unistd.h>
f9e5ce61
PMF
8
9#include <stdio.h>
10#include <stdlib.h>
d0b5f2b9 11#include <string.h>
b0540e11 12#include <execinfo.h>
d0b5f2b9
PMF
13
14#include "ustcomm.h"
15#include "localerr.h"
f9e5ce61
PMF
16
17#define UNIX_PATH_MAX 108
18#define SOCK_DIR "/tmp/socks"
19#define UST_SIGNAL SIGIO
20
d0b5f2b9
PMF
21#define MSG_MAX 1000
22
3847c3ba
PMF
23//static void bt(void)
24//{
25// void *buffer[100];
26// int result;
27//
28// result = backtrace(&buffer, 100);
29// backtrace_symbols_fd(buffer, result, STDERR_FILENO);
30//}
b0540e11 31
f9e5ce61
PMF
32static void signal_process(pid_t pid)
33{
34 int result;
35
36 result = kill(pid, UST_SIGNAL);
37 if(result == -1) {
b0540e11 38 PERROR("kill");
f9e5ce61
PMF
39 return;
40 }
41
42 sleep(1);
43}
44
b0540e11 45int send_message_path(const char *path, const char *msg, char **reply, int signalpid)
f9e5ce61
PMF
46{
47 int fd;
48 int result;
49 struct sockaddr_un addr;
f9e5ce61
PMF
50
51 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
52 if(result == -1) {
b0540e11 53 PERROR("socket");
d0b5f2b9 54 return -1;
f9e5ce61
PMF
55 }
56
57 addr.sun_family = AF_UNIX;
58
b0540e11 59 result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s", path);
f9e5ce61 60 if(result >= UNIX_PATH_MAX) {
b0540e11 61 ERR("string overflow allocating socket name");
d0b5f2b9 62 return -1;
f9e5ce61
PMF
63 }
64
b0540e11
PMF
65 if(signalpid >= 0)
66 signal_process(signalpid);
f9e5ce61 67
d0b5f2b9 68 result = sendto(fd, msg, strlen(msg), 0, (struct sockaddr *)&addr, sizeof(addr));
f9e5ce61 69 if(result == -1) {
b0540e11 70 PERROR("sendto");
d0b5f2b9 71 return -1;
f9e5ce61
PMF
72 }
73
d0b5f2b9
PMF
74 if(!reply)
75 return 0;
76
77 *reply = (char *) malloc(MSG_MAX+1);
78 result = recvfrom(fd, *reply, MSG_MAX, 0, NULL, NULL);
79 if(result == -1) {
b0540e11 80 PERROR("recvfrom");
d0b5f2b9
PMF
81 return -1;
82 }
83
84 (*reply)[result] = '\0';
f9e5ce61
PMF
85
86 return 0;
87}
88
b0540e11
PMF
89/* pid: the pid of the trace process that must receive the msg
90 msg: pointer to a null-terminated message to send
91 reply: location where to put the null-terminated string of the reply;
92 it must be free'd after usage
93 */
94
95int send_message(pid_t pid, const char *msg, char **reply)
96{
97 int result;
98 char path[UNIX_PATH_MAX];
99
100 result = snprintf(path, UNIX_PATH_MAX, "%s/%d", SOCK_DIR, pid);
101 if(result >= UNIX_PATH_MAX) {
102 fprintf(stderr, "string overflow allocating socket name");
103 return -1;
104 }
105
106 send_message_path(path, msg, reply, pid);
107
108 return 0;
109}
110
111/* Called by an app to ask the consumer daemon to connect to it. */
112
113int ustcomm_request_consumer(pid_t pid, const char *channel)
114{
115 char path[UNIX_PATH_MAX];
116 int result;
117 char *msg;
118
119 result = snprintf(path, UNIX_PATH_MAX, "%s/ustd", SOCK_DIR);
120 if(result >= UNIX_PATH_MAX) {
121 fprintf(stderr, "string overflow allocating socket name");
122 return -1;
123 }
124
125 asprintf(&msg, "collect %d %s", pid, channel);
126
3847c3ba 127 send_message_path(path, msg, NULL, -1);
b0540e11
PMF
128 free(msg);
129
130 return 0;
131}
132
b02e31e5 133static int recv_message_fd(int fd, char **msg, struct ustcomm_source *src)
d0b5f2b9 134{
d0b5f2b9 135 int result;
b02e31e5 136 size_t initial_addrlen,addrlen;
d0b5f2b9
PMF
137
138 *msg = (char *) malloc(MSG_MAX+1);
b02e31e5
PMF
139
140 if(src) {
141 initial_addrlen = addrlen = sizeof(src->addr);
142
143 result = recvfrom(fd, *msg, MSG_MAX, 0, &src->addr, &addrlen);
144 if(initial_addrlen != addrlen) {
145 ERR("recvfrom: unexpected address length");
146 return -1;
147 }
148 }
149 else {
150 result = recvfrom(fd, *msg, MSG_MAX, 0, NULL, NULL);
151 }
152
d0b5f2b9
PMF
153 if(result == -1) {
154 PERROR("recvfrom");
155 return -1;
156 }
b0540e11 157
d0b5f2b9 158 (*msg)[result] = '\0';
b0540e11
PMF
159
160 DBG("ustcomm_app_recv_message: result is %d, message is %s", result, (*msg));
161
d0b5f2b9
PMF
162 return 0;
163}
164
b02e31e5 165int ustcomm_ustd_recv_message(struct ustcomm_ustd *ustd, char **msg, struct ustcomm_source *src)
b0540e11 166{
b02e31e5 167 return recv_message_fd(ustd->fd, msg, src);
b0540e11
PMF
168}
169
b02e31e5 170int ustcomm_app_recv_message(struct ustcomm_app *app, char **msg, struct ustcomm_source *src)
b0540e11 171{
b02e31e5 172 return recv_message_fd(app->fd, msg, src);
b0540e11
PMF
173}
174
d0b5f2b9
PMF
175static int init_named_socket(char *name, char **path_out)
176{
177 int result;
178 int fd;
179
180 struct sockaddr_un addr;
181
182 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
183 if(result == -1) {
184 PERROR("socket");
185 return -1;
186 }
187
188 addr.sun_family = AF_UNIX;
189
190 strncpy(addr.sun_path, name, UNIX_PATH_MAX);
191 addr.sun_path[UNIX_PATH_MAX-1] = '\0';
192
193 result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
194 if(result == -1) {
195 PERROR("bind");
196 goto close_sock;
197 }
198
b0540e11
PMF
199 if(path_out) {
200 *path_out = "";
d0b5f2b9 201 *path_out = strdupa(addr.sun_path);
b0540e11 202 }
d0b5f2b9
PMF
203
204 return fd;
205
206 close_sock:
207 close(fd);
208
209 return -1;
210}
211
212int ustcomm_init_app(pid_t pid, struct ustcomm_app *handle)
213{
214 int result;
215 char *name;
216
217 result = asprintf(&name, "%s/%d", SOCK_DIR, (int)pid);
218 if(result >= UNIX_PATH_MAX) {
219 ERR("string overflow allocating socket name");
220 return -1;
221 }
222
b0540e11 223 handle->fd = init_named_socket(name, &(handle->socketpath));
d0b5f2b9
PMF
224 if(handle->fd < 0) {
225 goto free_name;
226 }
227 free(name);
228
229 return 0;
230
231free_name:
232 free(name);
233 return -1;
234}
235
236int ustcomm_init_ustd(struct ustcomm_ustd *handle)
237{
3847c3ba
PMF
238 int result;
239 char *name;
240
241 result = asprintf(&name, "%s/%s", SOCK_DIR, "ustd");
242 if(result >= UNIX_PATH_MAX) {
243 ERR("string overflow allocating socket name");
244 return -1;
245 }
246
247 handle->fd = init_named_socket(name, &handle->socketpath);
d0b5f2b9
PMF
248 if(handle->fd < 0)
249 return handle->fd;
3847c3ba 250 free(name);
d0b5f2b9
PMF
251
252 return 0;
253}
b02e31e5
PMF
254
255char *find_tok(const char *str)
256{
257 while(*str == ' ') {
258 str++;
259
260 if(*str == 0)
261 return NULL;
262 }
263
264 return str;
265}
266
267static char *find_sep(char *str)
268{
269 while(*str != ' ') {
270 str++;
271
272 if(*str == 0)
273 break;
274 }
275
276 return str;
277}
278
279int nth_token_is(char *str, char *token, int tok_no)
280{
281 int i;
282 char *start;
283 char *end;
284
285 for(i=0; i<=tok_no; i++) {
286 str = find_tok(str);
287 if(str == NULL)
288 return -1;
289
290 start = str;
291
292 str = find_sep(str);
293 if(str == NULL)
294 return -1;
295
296 end = str;
297 }
298
299 if(end-start != strlen(token))
300 return 0;
301
302 if(strncmp(start, token, end-start))
303 return 0;
304
305 return 1;
306}
307
308char *nth_token(char *str, int tok_no)
309{
310 static char *retval = NULL;
311 int i;
312 char *start;
313 char *end;
314
315 for(i=0; i<=tok_no; i++) {
316 str = find_tok(str);
317 if(str == NULL)
318 return NULL;
319
320 start = str;
321
322 str = find_sep(str);
323 if(str == NULL)
324 return NULL;
325
326 end = str;
327 }
328
329 if(retval) {
330 free(retval);
331 retval = NULL;
332 }
333
334 retval = strndupa(start, end-start);
335
336 return retval;
337}
338
This page took 0.035262 seconds and 4 git commands to generate.