Change licensing
[lttng-tools.git] / liblttngctl / liblttngctl.c
CommitLineData
826d496d 1/*
82a3637f
DG
2 * liblttngctl.c
3 *
4 * Linux Trace Toolkit Control Library
5 *
826d496d 6 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
fac6795d 7 *
82a3637f
DG
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
fac6795d 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
82a3637f
DG
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
fac6795d
DG
21 */
22
23#define _GNU_SOURCE
24#include <errno.h>
25#include <grp.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
5b97ec60 31#include <lttng/lttng.h>
fac6795d
DG
32
33#include "liblttsessiondcomm.h"
34#include "lttngerr.h"
f3ed775e 35#include "lttng-share.h"
fac6795d
DG
36
37/* Socket to session daemon for communication */
38static int sessiond_socket;
39static char sessiond_sock_path[PATH_MAX];
40
41/* Communication structure to ltt-sessiond */
fac6795d 42static struct lttcomm_session_msg lsm;
5461b305 43static struct lttcomm_lttng_msg llm;
fac6795d 44
fac6795d
DG
45/* Variables */
46static char *tracing_group;
47static int connected;
48
49/*
ca95a216 50 * send_data_sessiond
fac6795d 51 *
e065084a 52 * Send lttcomm_session_msg to the session daemon.
fac6795d
DG
53 *
54 * On success, return 0
55 * On error, return error code
56 */
ca95a216 57static int send_data_sessiond(void)
fac6795d
DG
58{
59 int ret;
60
61 if (!connected) {
e065084a
DG
62 ret = -ENOTCONN;
63 goto end;
fac6795d
DG
64 }
65
66 ret = lttcomm_send_unix_sock(sessiond_socket, &lsm, sizeof(lsm));
e065084a
DG
67
68end:
69 return ret;
70}
71
72/*
ca95a216 73 * recv_data_sessiond
e065084a
DG
74 *
75 * Receive data from the sessiond socket.
76 *
77 * On success, return 0
78 * On error, return recv() error code
79 */
ca95a216 80static int recv_data_sessiond(void *buf, size_t len)
e065084a
DG
81{
82 int ret;
83
84 if (!connected) {
85 ret = -ENOTCONN;
86 goto end;
fac6795d
DG
87 }
88
ca95a216 89 ret = lttcomm_recv_unix_sock(sessiond_socket, buf, len);
fac6795d 90
e065084a 91end:
fac6795d
DG
92 return ret;
93}
94
95/*
947308c4 96 * Check if the specified group name exist.
65beb5ff
DG
97 *
98 * If yes return 0, else return -1.
947308c4
DG
99 */
100static int check_tracing_group(const char *grp_name)
101{
102 struct group *grp_tracing; /* no free(). See getgrnam(3) */
103 gid_t *grp_list;
104 int grp_list_size, grp_id, i;
105 int ret = -1;
106
107 /* Get GID of group 'tracing' */
108 grp_tracing = getgrnam(grp_name);
109 if (grp_tracing == NULL) {
110 /* NULL means not found also. getgrnam(3) */
111 if (errno != 0) {
112 perror("getgrnam");
113 }
114 goto end;
115 }
116
117 /* Get number of supplementary group IDs */
118 grp_list_size = getgroups(0, NULL);
119 if (grp_list_size < 0) {
120 perror("getgroups");
121 goto end;
122 }
123
124 /* Alloc group list of the right size */
125 grp_list = malloc(grp_list_size * sizeof(gid_t));
126 grp_id = getgroups(grp_list_size, grp_list);
127 if (grp_id < -1) {
128 perror("getgroups");
129 goto free_list;
130 }
131
132 for (i = 0; i < grp_list_size; i++) {
133 if (grp_list[i] == grp_tracing->gr_gid) {
134 ret = 0;
135 break;
136 }
137 }
138
139free_list:
140 free(grp_list);
141
142end:
143 return ret;
144}
145
146/*
65beb5ff
DG
147 * Set sessiond socket path by putting it in the global sessiond_sock_path
148 * variable.
947308c4
DG
149 */
150static int set_session_daemon_path(void)
151{
152 int ret;
153
154 /* Are we in the tracing group ? */
155 ret = check_tracing_group(tracing_group);
156 if (ret < 0 && getuid() != 0) {
157 if (sprintf(sessiond_sock_path, DEFAULT_HOME_CLIENT_UNIX_SOCK,
158 getenv("HOME")) < 0) {
159 return -ENOMEM;
160 }
161 } else {
162 strncpy(sessiond_sock_path, DEFAULT_GLOBAL_CLIENT_UNIX_SOCK,
163 sizeof(DEFAULT_GLOBAL_CLIENT_UNIX_SOCK));
164 }
165
166 return 0;
167}
168
65beb5ff
DG
169/*
170 * Connect to the LTTng session daemon.
171 *
172 * On success, return 0. On error, return -1.
173 */
174static int connect_sessiond(void)
175{
176 int ret;
177
178 ret = set_session_daemon_path();
179 if (ret < 0) {
180 return ret;
181 }
182
183 /* Connect to the sesssion daemon */
184 ret = lttcomm_connect_unix_sock(sessiond_sock_path);
185 if (ret < 0) {
186 return ret;
187 }
188
189 sessiond_socket = ret;
190 connected = 1;
191
192 return 0;
193}
194
195/*
196 * Clean disconnect the session daemon.
197 */
198static int disconnect_sessiond(void)
199{
200 int ret = 0;
201
202 if (connected) {
203 ret = lttcomm_close_unix_sock(sessiond_socket);
204 sessiond_socket = 0;
205 connected = 0;
206 }
207
208 return ret;
209}
210
211/*
212 * ask_sessiond
213 *
214 * Ask the session daemon a specific command and put the data into buf.
215 *
216 * Return size of data (only payload, not header).
217 */
218static int ask_sessiond(enum lttcomm_sessiond_command lct, void **buf)
219{
220 int ret;
221 size_t size;
222 void *data = NULL;
223
224 ret = connect_sessiond();
225 if (ret < 0) {
226 goto end;
227 }
228
229 lsm.cmd_type = lct;
230
231 /* Send command to session daemon */
232 ret = send_data_sessiond();
233 if (ret < 0) {
234 goto end;
235 }
236
237 /* Get header from data transmission */
238 ret = recv_data_sessiond(&llm, sizeof(llm));
239 if (ret < 0) {
240 goto end;
241 }
242
243 /* Check error code if OK */
244 if (llm.ret_code != LTTCOMM_OK) {
245 ret = -llm.ret_code;
246 goto end;
247 }
248
249 size = llm.data_size;
250 if (size == 0) {
7d29a247 251 ret = 0;
65beb5ff
DG
252 goto end;
253 }
254
255 data = (void*) malloc(size);
256
257 /* Get payload data */
258 ret = recv_data_sessiond(data, size);
259 if (ret < 0) {
260 free(data);
261 goto end;
262 }
263
264 *buf = data;
265 ret = size;
266
267end:
268 disconnect_sessiond();
269 return ret;
270}
271
1df4dedd 272/*
f3ed775e 273 * Start tracing for all trace of the session.
1df4dedd 274 */
38057ed1 275int lttng_start_tracing(const char *session_name)
f3ed775e
DG
276{
277 strncpy(lsm.session_name, session_name, NAME_MAX);
278 return ask_sessiond(LTTNG_START_TRACE, NULL);
279}
1df4dedd
DG
280
281/*
f3ed775e
DG
282 * Stop tracing for all trace of the session.
283 */
38057ed1 284int lttng_stop_tracing(const char *session_name)
f3ed775e
DG
285{
286 strncpy(lsm.session_name, session_name, NAME_MAX);
287 return ask_sessiond(LTTNG_STOP_TRACE, NULL);
288}
289
290/*
7d29a247 291 * lttng_add_context
1df4dedd 292 */
7d29a247 293int lttng_add_context(struct lttng_domain *domain,
38057ed1
DG
294 struct lttng_event_context *ctx, const char *event_name,
295 const char *channel_name)
d65106b1 296{
7d29a247
DG
297 int ret;
298
94cf3c47 299 if (channel_name != NULL) {
d65106b1
DG
300 strncpy(lsm.u.context.channel_name, channel_name, NAME_MAX);
301 }
302
94cf3c47 303 if (event_name != NULL) {
d65106b1
DG
304 strncpy(lsm.u.context.event_name, event_name, NAME_MAX);
305 }
306
7d29a247
DG
307 memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context));
308
309 switch (domain->type) {
310 case LTTNG_DOMAIN_KERNEL:
311 ret = ask_sessiond(LTTNG_KERNEL_ADD_CONTEXT, NULL);
312 break;
313 case LTTNG_DOMAIN_UST:
314 ret = LTTCOMM_NOT_IMPLEMENTED;
315 break;
316 default:
317 ret = LTTCOMM_UNKNOWN_DOMAIN;
318 break;
319 };
320
321 return ret;
d65106b1
DG
322}
323
f3ed775e 324/*
7d29a247 325 * lttng_enable_event
f3ed775e 326 */
7d29a247 327int lttng_enable_event(struct lttng_domain *domain,
38057ed1 328 struct lttng_event *ev, const char *channel_name)
1df4dedd 329{
33a2b854
DG
330 int ret;
331
94cf3c47 332 if (channel_name == NULL) {
f3ed775e 333 strncpy(lsm.u.enable.channel_name, DEFAULT_CHANNEL_NAME, NAME_MAX);
33a2b854 334 } else {
f3ed775e
DG
335 strncpy(lsm.u.enable.channel_name, channel_name, NAME_MAX);
336 }
337
7d29a247
DG
338 switch (domain->type) {
339 case LTTNG_DOMAIN_KERNEL:
340 if (ev == NULL) {
341 ret = ask_sessiond(LTTNG_KERNEL_ENABLE_ALL_EVENT, NULL);
342 } else {
343 memcpy(&lsm.u.enable.event, ev, sizeof(struct lttng_event));
344 ret = ask_sessiond(LTTNG_KERNEL_ENABLE_EVENT, NULL);
345 }
346 break;
347 case LTTNG_DOMAIN_UST:
348 ret = LTTCOMM_NOT_IMPLEMENTED;
349 break;
350 default:
351 ret = LTTCOMM_UNKNOWN_DOMAIN;
352 break;
353 };
33a2b854
DG
354
355 return ret;
1df4dedd
DG
356}
357
358/*
7d29a247 359 * Disable an event in the kernel tracer.
1df4dedd 360 */
38057ed1
DG
361int lttng_disable_event(struct lttng_domain *domain, const char *name,
362 const char *channel_name)
1df4dedd 363{
f3ed775e 364 int ret;
1df4dedd 365
94cf3c47 366 if (channel_name == NULL) {
f3ed775e
DG
367 strncpy(lsm.u.disable.channel_name, DEFAULT_CHANNEL_NAME, NAME_MAX);
368 } else {
369 strncpy(lsm.u.disable.channel_name, channel_name, NAME_MAX);
370 }
371
7d29a247
DG
372 switch (domain->type) {
373 case LTTNG_DOMAIN_KERNEL:
374 if (name == NULL) {
375 ret = ask_sessiond(LTTNG_KERNEL_DISABLE_ALL_EVENT, NULL);
376 } else {
377 strncpy(lsm.u.disable.name, name, NAME_MAX);
378 ret = ask_sessiond(LTTNG_KERNEL_DISABLE_EVENT, NULL);
379 }
380 break;
381 case LTTNG_DOMAIN_UST:
382 ret = LTTCOMM_NOT_IMPLEMENTED;
383 break;
384 default:
385 ret = LTTCOMM_UNKNOWN_DOMAIN;
386 break;
387 };
f3ed775e
DG
388
389 return ret;
1df4dedd
DG
390}
391
392/*
7d29a247 393 * Enable recording for a channel for the kernel tracer.
a5c5a2bd 394 */
38057ed1
DG
395int lttng_enable_channel(struct lttng_domain *domain,
396 struct lttng_channel *chan)
a5c5a2bd 397{
7d29a247 398 int ret;
8c0faa1d 399
f3ed775e 400 memcpy(&lsm.u.channel.chan, chan, sizeof(struct lttng_channel));
7d29a247
DG
401
402 switch (domain->type) {
403 case LTTNG_DOMAIN_KERNEL:
404 ret = ask_sessiond(LTTNG_KERNEL_ENABLE_CHANNEL, NULL);
405 break;
406 case LTTNG_DOMAIN_UST:
407 ret = LTTCOMM_NOT_IMPLEMENTED;
408 break;
409 default:
410 ret = LTTCOMM_UNKNOWN_DOMAIN;
411 break;
412 };
413
414 return ret;
8c0faa1d 415}
1df4dedd 416
2ef84c95 417/*
7d29a247 418 * Disable recording for the channel for the kernel tracer.
2ef84c95 419 */
38057ed1 420int lttng_disable_channel(struct lttng_domain *domain, const char *name)
2ef84c95 421{
7d29a247 422 int ret;
2ef84c95 423
7d29a247 424 strncpy(lsm.u.disable.channel_name, name, NAME_MAX);
1df4dedd 425
7d29a247
DG
426 switch (domain->type) {
427 case LTTNG_DOMAIN_KERNEL:
428 ret = ask_sessiond(LTTNG_KERNEL_DISABLE_CHANNEL, NULL);
429 break;
430 case LTTNG_DOMAIN_UST:
431 ret = LTTCOMM_NOT_IMPLEMENTED;
432 break;
433 default:
434 ret = LTTCOMM_UNKNOWN_DOMAIN;
435 break;
436 };
ca95a216 437
7d29a247 438 return ret;
ca95a216
DG
439}
440
fac6795d 441/*
7d29a247 442 * List all available events in the kernel.
fac6795d 443 *
7d29a247
DG
444 * Return the size (bytes) of the list and set the event_list array.
445 * On error, return negative value.
fac6795d 446 */
7d29a247 447int lttng_list_events(struct lttng_domain *domain, char **event_list)
fac6795d 448{
ca95a216 449 int ret;
fac6795d 450
7d29a247
DG
451 switch (domain->type) {
452 case LTTNG_DOMAIN_KERNEL:
453 ret = ask_sessiond(LTTNG_KERNEL_LIST_EVENTS, (void **) event_list);
454 break;
455 case LTTNG_DOMAIN_UST:
456 ret = LTTCOMM_NOT_IMPLEMENTED;
457 break;
458 default:
459 ret = LTTCOMM_UNKNOWN_DOMAIN;
460 break;
461 };
fac6795d 462
7d29a247 463 return ret;
fac6795d
DG
464}
465
1657e9bb 466/*
7d29a247 467 * Return a human readable string of code
1657e9bb 468 */
7d29a247 469const char *lttng_get_readable_code(int code)
1657e9bb 470{
7d29a247
DG
471 if (code > -LTTCOMM_OK) {
472 return "Ended with errors";
1657e9bb
DG
473 }
474
7d29a247 475 return lttcomm_get_readable_code(code);
1657e9bb
DG
476}
477
aaf97519 478/*
894be886 479 * Create a brand new session using name.
aaf97519 480 */
38057ed1 481int lttng_create_session(const char *name, const char *path)
aaf97519 482{
947308c4 483 strncpy(lsm.session_name, name, NAME_MAX);
f3ed775e 484 strncpy(lsm.path, path, PATH_MAX);
947308c4 485 return ask_sessiond(LTTNG_CREATE_SESSION, NULL);
8028d920
DG
486}
487
488/*
8028d920
DG
489 * Destroy session using name.
490 */
38057ed1 491int lttng_destroy_session(const char *name)
8028d920 492{
f3ed775e 493 strncpy(lsm.session_name, name, NAME_MAX);
947308c4 494 return ask_sessiond(LTTNG_DESTROY_SESSION, NULL);
aaf97519
DG
495}
496
57167058 497/*
57167058
DG
498 * Ask the session daemon for all available sessions.
499 *
ca95a216
DG
500 * Return number of session.
501 * On error, return negative value.
57167058 502 */
ca95a216 503int lttng_list_sessions(struct lttng_session **sessions)
57167058 504{
ca95a216 505 int ret;
57167058 506
ca95a216 507 ret = ask_sessiond(LTTNG_LIST_SESSIONS, (void**) sessions);
57167058 508 if (ret < 0) {
ca95a216 509 return ret;
57167058
DG
510 }
511
ca95a216 512 return ret / sizeof(struct lttng_session);
57167058
DG
513}
514
7d29a247
DG
515/*
516 * Set session name for the current lsm.
517 */
38057ed1 518void lttng_set_session_name(const char *name)
e8be5f4f 519{
f3ed775e 520 strncpy(lsm.session_name, name, NAME_MAX);
e8be5f4f
DG
521}
522
fac6795d
DG
523/*
524 * lttng_set_tracing_group
525 *
526 * Set tracing group variable with name. This function
527 * allocate memory pointed by tracing_group.
528 */
529int lttng_set_tracing_group(const char *name)
530{
531 if (asprintf(&tracing_group, "%s", name) < 0) {
532 return -ENOMEM;
533 }
534
535 return 0;
536}
537
538/*
539 * lttng_check_session_daemon
540 *
947308c4
DG
541 * Yes, return 1
542 * No, return 0
543 * Error, return negative value
fac6795d 544 */
947308c4 545int lttng_session_daemon_alive(void)
fac6795d
DG
546{
547 int ret;
548
549 ret = set_session_daemon_path();
550 if (ret < 0) {
947308c4 551 /* Error */
fac6795d
DG
552 return ret;
553 }
554
555 /* If socket exist, we consider the daemon started */
556 ret = access(sessiond_sock_path, F_OK);
557 if (ret < 0) {
947308c4
DG
558 /* Not alive */
559 return 0;
fac6795d
DG
560 }
561
947308c4
DG
562 /* Is alive */
563 return 1;
fac6795d
DG
564}
565
566/*
567 * lib constructor
568 */
569static void __attribute__((constructor)) init()
570{
571 /* Set default session group */
64a23ac4 572 lttng_set_tracing_group(LTTNG_DEFAULT_TRACING_GROUP);
fac6795d 573}
This page took 0.051691 seconds and 5 git commands to generate.