ust: continue implementation of ustd
[ust.git] / libustcomm / ustcomm.c
1 #define _GNU_SOURCE
2 #include <sys/types.h>
3 #include <signal.h>
4 #include <errno.h>
5 #include <sys/socket.h>
6 #include <sys/un.h>
7 #include <unistd.h>
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <execinfo.h>
13
14 #include "ustcomm.h"
15 #include "localerr.h"
16
17 #define UNIX_PATH_MAX 108
18 #define SOCK_DIR "/tmp/socks"
19 #define UST_SIGNAL SIGIO
20
21 #define MSG_MAX 1000
22
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 //}
31
32 static void signal_process(pid_t pid)
33 {
34 int result;
35
36 result = kill(pid, UST_SIGNAL);
37 if(result == -1) {
38 PERROR("kill");
39 return;
40 }
41
42 sleep(1);
43 }
44
45 int send_message_path(const char *path, const char *msg, char **reply, int signalpid)
46 {
47 int fd;
48 int result;
49 struct sockaddr_un addr;
50
51 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
52 if(result == -1) {
53 PERROR("socket");
54 return -1;
55 }
56
57 addr.sun_family = AF_UNIX;
58
59 result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s", path);
60 if(result >= UNIX_PATH_MAX) {
61 ERR("string overflow allocating socket name");
62 return -1;
63 }
64
65 if(signalpid >= 0)
66 signal_process(signalpid);
67
68 result = sendto(fd, msg, strlen(msg), 0, (struct sockaddr *)&addr, sizeof(addr));
69 if(result == -1) {
70 PERROR("sendto");
71 return -1;
72 }
73
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) {
80 PERROR("recvfrom");
81 return -1;
82 }
83
84 (*reply)[result] = '\0';
85
86 return 0;
87 }
88
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
95 int 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
113 int 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
127 send_message_path(path, msg, NULL, -1);
128 free(msg);
129
130 return 0;
131 }
132
133 static int recv_message_fd(int fd, char **msg)
134 {
135 int result;
136
137 *msg = (char *) malloc(MSG_MAX+1);
138 result = recvfrom(fd, *msg, MSG_MAX, 0, NULL, NULL);
139 if(result == -1) {
140 PERROR("recvfrom");
141 return -1;
142 }
143
144 (*msg)[result] = '\0';
145
146 DBG("ustcomm_app_recv_message: result is %d, message is %s", result, (*msg));
147
148 return 0;
149 }
150
151 int ustcomm_ustd_recv_message(struct ustcomm_ustd *ustd, char **msg)
152 {
153 return recv_message_fd(ustd->fd, msg);
154 }
155
156 int ustcomm_app_recv_message(struct ustcomm_app *app, char **msg)
157 {
158 return recv_message_fd(app->fd, msg);
159 }
160
161 static int init_named_socket(char *name, char **path_out)
162 {
163 int result;
164 int fd;
165
166 struct sockaddr_un addr;
167
168 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
169 if(result == -1) {
170 PERROR("socket");
171 return -1;
172 }
173
174 addr.sun_family = AF_UNIX;
175
176 strncpy(addr.sun_path, name, UNIX_PATH_MAX);
177 addr.sun_path[UNIX_PATH_MAX-1] = '\0';
178
179 result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
180 if(result == -1) {
181 PERROR("bind");
182 goto close_sock;
183 }
184
185 if(path_out) {
186 *path_out = "";
187 *path_out = strdupa(addr.sun_path);
188 }
189
190 return fd;
191
192 close_sock:
193 close(fd);
194
195 return -1;
196 }
197
198 int ustcomm_init_app(pid_t pid, struct ustcomm_app *handle)
199 {
200 int result;
201 char *name;
202
203 result = asprintf(&name, "%s/%d", SOCK_DIR, (int)pid);
204 if(result >= UNIX_PATH_MAX) {
205 ERR("string overflow allocating socket name");
206 return -1;
207 }
208
209 handle->fd = init_named_socket(name, &(handle->socketpath));
210 if(handle->fd < 0) {
211 goto free_name;
212 }
213 free(name);
214
215 return 0;
216
217 free_name:
218 free(name);
219 return -1;
220 }
221
222 int ustcomm_init_ustd(struct ustcomm_ustd *handle)
223 {
224 int result;
225 char *name;
226
227 result = asprintf(&name, "%s/%s", SOCK_DIR, "ustd");
228 if(result >= UNIX_PATH_MAX) {
229 ERR("string overflow allocating socket name");
230 return -1;
231 }
232
233 handle->fd = init_named_socket(name, &handle->socketpath);
234 if(handle->fd < 0)
235 return handle->fd;
236 free(name);
237
238 return 0;
239 }
This page took 0.033107 seconds and 4 git commands to generate.