Initial import
[lttng-tools.git] / liblttngctl / liblttngctl.c
CommitLineData
fac6795d
DG
1/* Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2
6 * of the License, or (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 *
17 */
18
19#define _GNU_SOURCE
20#include <errno.h>
21#include <grp.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include <lttng/liblttngctl.h>
28
29#include "liblttsessiondcomm.h"
30#include "lttngerr.h"
31
32/* Socket to session daemon for communication */
33static int sessiond_socket;
34static char sessiond_sock_path[PATH_MAX];
35
36/* Communication structure to ltt-sessiond */
37static struct lttcomm_lttng_msg llm;
38static struct lttcomm_session_msg lsm;
39
40/* Prototypes */
41static int check_tracing_group(const char *grp_name);
42static int ask_sessiond(void);
43static int set_session_daemon_path(void);
44static void reset_data_struct(void);
45
46int lttng_connect_sessiond(void);
47int lttng_create_session(const char *name, char *session_id);
48int lttng_check_session_daemon(void);
49
50/* Variables */
51static char *tracing_group;
52static int connected;
53
54/*
55 * ask_sessiond
56 *
57 * Send lttcomm_session_msg to the daemon and wait
58 * for the reply. Data replied will be put in llm
59 *
60 * On success, return 0
61 * On error, return error code
62 */
63static int ask_sessiond(void)
64{
65 int ret;
66
67 if (!connected) {
68 ret = -ECONNREFUSED;
69 goto error;
70 }
71
72 ret = lttcomm_send_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
73 if (ret < 0) {
74 goto error;
75 }
76
77 ret = lttcomm_recv_unix_sock(sessiond_socket, &llm, sizeof(llm));
78 if (ret < 0) {
79 goto error;
80 }
81
82 /* Check return code */
83 if (llm.ret_code != LTTCOMM_OK) {
84 ret = -llm.ret_code;
85 goto error;
86 }
87
88 return 0;
89
90error:
91 return ret;
92}
93
94/*
95 * lttng_get_readable_code
96 *
97 * Return a human readable string of code
98 */
99const char *lttng_get_readable_code(int code)
100{
101 if (code > -LTTCOMM_OK) {
102 return "Ended with errors";
103 }
104
105 return lttcomm_get_readable_code(code);
106}
107
108/*
109 * lttng_create_session
110 *
111 * Create a tracing session using "name" to the session daemon.
112 * If no name is given, the auto session creation is set and
113 * the daemon will take care of finding a name.
114 *
115 * On success, return 0 and session_id point to the uuid str.
116 * On error, negative value is returned.
117 */
118int lttng_create_session(const char *name, char *session_id)
119{
120 int ret;
121
122 lsm.cmd_type = LTTNG_CREATE_SESSION;
123 if (name == NULL) {
124 lsm.u.create_session.auto_session = 1;
125 } else {
126 strncpy(lsm.session_name, name, strlen(name));
127 lsm.u.create_session.auto_session = 0;
128 }
129
130 /* Ask the session daemon */
131 ret = ask_sessiond();
132 if (ret < 0) {
133 goto end;
134 }
135
136 /* Unparse session ID */
137 uuid_unparse(llm.session_id, session_id);
138
139end:
140 reset_data_struct();
141
142 return ret;
143}
144
145/*
146 * lttng_ust_list_apps
147 *
148 * Ask the session daemon for all UST traceable
149 * applications.
150 *
151 * Return the size of pids.
152 */
153size_t lttng_ust_list_apps(pid_t **pids)
154{
155 int ret;
156
157 lsm.cmd_type = UST_LIST_APPS;
158
159 ret = ask_sessiond();
160 if (ret < 0) {
161 goto error;
162 }
163
164 *pids = llm.u.list_apps.pids;
165
166 return llm.u.list_apps.size;
167
168error:
169 return ret;
170}
171
172/*
173 * lttng_connect_sessiond
174 *
175 * Connect to the LTTng session daemon.
176 * On success, return 0
177 * On error, return a negative value
178 */
179int lttng_connect_sessiond(void)
180{
181 int ret;
182
183 ret = set_session_daemon_path();
184 if (ret < 0) {
185 return ret;
186 }
187
188 /* Connect to the sesssion daemon */
189 ret = lttcomm_connect_unix_sock(sessiond_sock_path);
190 if (ret < 0) {
191 return ret;
192 }
193
194 sessiond_socket = ret;
195 connected = 1;
196
197 return 0;
198}
199
200/*
201 * lttng_set_tracing_group
202 *
203 * Set tracing group variable with name. This function
204 * allocate memory pointed by tracing_group.
205 */
206int lttng_set_tracing_group(const char *name)
207{
208 if (asprintf(&tracing_group, "%s", name) < 0) {
209 return -ENOMEM;
210 }
211
212 return 0;
213}
214
215/*
216 * lttng_check_session_daemon
217 *
218 * Return 0 if a sesssion daemon is available
219 * else return -1
220 */
221int lttng_check_session_daemon(void)
222{
223 int ret;
224
225 ret = set_session_daemon_path();
226 if (ret < 0) {
227 return ret;
228 }
229
230 /* If socket exist, we consider the daemon started */
231 ret = access(sessiond_sock_path, F_OK);
232 if (ret < 0) {
233 return ret;
234 }
235
236 return 0;
237}
238
239/*
240 * reset_data_struct
241 *
242 * Reset session daemon structures.
243 */
244static void reset_data_struct(void)
245{
246 memset(&lsm, 0, sizeof(lsm));
247 memset(&llm, 0, sizeof(llm));
248}
249
250/*
251 * set_session_daemon_path
252 *
253 * Set sessiond socket path by putting it in
254 * the global sessiond_sock_path variable.
255 */
256static int set_session_daemon_path(void)
257{
258 int ret;
259
260 /* Are we in the tracing group ? */
261 ret = check_tracing_group(tracing_group);
262 if (ret < 0) {
263 if (sprintf(sessiond_sock_path, DEFAULT_HOME_CLIENT_UNIX_SOCK,
264 getenv("HOME")) < 0) {
265 return -ENOMEM;
266 }
267 } else {
268 strncpy(sessiond_sock_path, DEFAULT_GLOBAL_CLIENT_UNIX_SOCK,
269 sizeof(DEFAULT_GLOBAL_CLIENT_UNIX_SOCK));
270 }
271
272 return 0;
273}
274
275/*
276 * check_tracing_group
277 *
278 * Check if the specified group name exist.
279 * If yes, 0, else -1
280 */
281static int check_tracing_group(const char *grp_name)
282{
283 struct group *grp_tracing; /* no free(). See getgrnam(3) */
284 gid_t *grp_list;
285 int grp_list_size, grp_id, i;
286 int ret = -1;
287
288 /* Get GID of group 'tracing' */
289 grp_tracing = getgrnam(grp_name);
290 if (grp_tracing == NULL) {
291 /* NULL means not found also. getgrnam(3) */
292 if (errno != 0) {
293 perror("getgrnam");
294 }
295 goto end;
296 }
297
298 /* Get number of supplementary group IDs */
299 grp_list_size = getgroups(0, NULL);
300 if (grp_list_size < 0) {
301 perror("getgroups");
302 goto end;
303 }
304
305 /* Alloc group list of the right size */
306 grp_list = malloc(grp_list_size * sizeof(gid_t));
307 grp_id = getgroups(grp_list_size, grp_list);
308 if (grp_id < -1) {
309 perror("getgroups");
310 goto free_list;
311 }
312
313 for (i = 0; i < grp_list_size; i++) {
314 if (grp_list[i] == grp_tracing->gr_gid) {
315 ret = 0;
316 break;
317 }
318 }
319
320free_list:
321 free(grp_list);
322
323end:
324 return ret;
325}
326
327/*
328 * lib constructor
329 */
330static void __attribute__((constructor)) init()
331{
332 /* Set default session group */
333 lttng_set_tracing_group(DEFAULT_TRACING_GROUP);
334}
This page took 0.051722 seconds and 4 git commands to generate.