add options to set subbuf size and cnt
[ust.git] / libustcmd / ustcmd.c
CommitLineData
ab33e65c
PP
1/* Copyright (C) 2009 Pierre-Marc Fournier, Philippe Proulx-Barrette
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library 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 GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
ef290fca 18#define _GNU_SOURCE
ab33e65c
PP
19#include <stdio.h>
20#include <unistd.h>
21#include <getopt.h>
22#include <stdlib.h>
23#include <fcntl.h>
24#include <string.h>
25#include <dirent.h>
ab33e65c
PP
26
27#include "ustcomm.h"
28#include "ustcmd.h"
29
08230db7 30pid_t *ustcmd_get_online_pids(void)
772030fe 31{
08230db7
PMF
32 struct dirent *dirent;
33 DIR *dir;
ef290fca 34 unsigned int ret_size = 1 * sizeof(pid_t), i = 0;
ab33e65c
PP
35
36 dir = opendir(SOCK_DIR);
37 if (!dir) {
38 return NULL;
39 }
40
08230db7 41 pid_t *ret = (pid_t *) malloc(ret_size);
ab33e65c 42
772030fe 43 while ((dirent = readdir(dir))) {
ab33e65c
PP
44 if (!strcmp(dirent->d_name, ".") ||
45 !strcmp(dirent->d_name, "..")) {
46
47 continue;
48 }
49
50 if (dirent->d_type != DT_DIR &&
51 !!strcmp(dirent->d_name, "ustd")) {
52
08230db7 53 sscanf(dirent->d_name, "%u", (unsigned int *) &ret[i]);
ab33e65c
PP
54 if (pid_is_online(ret[i])) {
55 ret_size += sizeof(pid_t);
08230db7 56 ret = (pid_t *) realloc(ret, ret_size);
ab33e65c
PP
57 ++i;
58 }
59 }
60 }
61
77957c95 62 ret[i] = 0; /* Array end */
ab33e65c 63
08230db7
PMF
64 if (ret[0] == 0) {
65 /* No PID at all */
ab33e65c
PP
66 free(ret);
67 return NULL;
68 }
69
70 closedir(dir);
71 return ret;
72}
73
74/**
75 * Sets marker state (USTCMD_MS_ON or USTCMD_MS_OFF).
76 *
77 * @param mn Marker name
78 * @param state Marker's new state
79 * @param pid Traced process ID
80 * @return 0 if successful, or errors {USTCMD_ERR_GEN, USTCMD_ERR_ARG}
81 */
08230db7 82int ustcmd_set_marker_state(const char *mn, int state, pid_t pid)
ef290fca 83{
08230db7
PMF
84 char *cmd_str [] = {"disable_marker", "enable_marker"};
85 char *cmd;
ef290fca
PMF
86 int result;
87
ab33e65c
PP
88 if (mn == NULL) {
89 return USTCMD_ERR_ARG;
90 }
91
ab33e65c
PP
92 asprintf(&cmd, "%s %s", cmd_str[state], mn);
93
08230db7 94 result = ustcmd_send_cmd(cmd, pid, NULL);
ef290fca 95 if (result) {
ab33e65c
PP
96 free(cmd);
97 return USTCMD_ERR_GEN;
98 }
99
100 free(cmd);
101 return 0;
102}
103
763f41e5
DS
104/**
105 * Set subbuffer size.
106 *
107 * @param channel_size Channel name and size
108 * @param pid Traced process ID
109 * @return 0 if successful, or error
110 */
111int ustcmd_set_subbuf_size(const char *channel_size, pid_t pid)
112{
113 char *cmd;
114 int result;
115
116 asprintf(&cmd, "%s %s", "set_subbuf_size", channel_size);
117
118 result = ustcmd_send_cmd(cmd, pid, NULL);
119 if (result) {
120 free(cmd);
121 return 1;
122 }
123
124 free(cmd);
125 return 0;
126}
127
128/**
129 * Set subbuffer num.
130 *
131 * @param channel_num Channel name and num
132 * @param pid Traced process ID
133 * @return 0 if successful, or error
134 */
135int ustcmd_set_subbuf_num(const char *channel_size, pid_t pid)
136{
137 char *cmd;
138 int result;
139
140 asprintf(&cmd, "%s %s", "set_subbuf_num", channel_size);
141
142 result = ustcmd_send_cmd(cmd, pid, NULL);
143 if (result) {
144 free(cmd);
145 return 1;
146 }
147
148 free(cmd);
149 return 0;
150}
151
152
ab33e65c
PP
153/**
154 * Destroys an UST trace according to a PID.
155 *
156 * @param pid Traced process ID
157 * @return 0 if successful, or error USTCMD_ERR_GEN
158 */
772030fe
PMF
159int ustcmd_destroy_trace(pid_t pid)
160{
161 int result;
ab33e65c 162
b5b073e2 163 result = ustcmd_send_cmd("trace_destroy", pid, NULL);
772030fe 164 if (result) {
ab33e65c
PP
165 return USTCMD_ERR_GEN;
166 }
167
168 return 0;
169}
170
171/**
172 * Starts an UST trace (and setups it) according to a PID.
173 *
174 * @param pid Traced process ID
175 * @return 0 if successful, or error USTCMD_ERR_GEN
176 */
772030fe
PMF
177int ustcmd_setup_and_start(pid_t pid)
178{
179 int result;
ab33e65c 180
08230db7 181 result = ustcmd_send_cmd("start", pid, NULL);
772030fe 182 if (result) {
ab33e65c
PP
183 return USTCMD_ERR_GEN;
184 }
185
186 return 0;
187}
188
62ec620f
PMF
189/**
190 * Creates an UST trace according to a PID.
191 *
192 * @param pid Traced process ID
193 * @return 0 if successful, or error USTCMD_ERR_GEN
194 */
195int ustcmd_create_trace(pid_t pid)
196{
197 int result;
198
199 result = ustcmd_send_cmd("trace_create", pid, NULL);
200 if (result) {
201 return USTCMD_ERR_GEN;
202 }
203
204 return 0;
205}
206
ab33e65c
PP
207/**
208 * Starts an UST trace according to a PID.
209 *
210 * @param pid Traced process ID
211 * @return 0 if successful, or error USTCMD_ERR_GEN
212 */
772030fe
PMF
213int ustcmd_start_trace(pid_t pid)
214{
215 int result;
ab33e65c 216
08230db7 217 result = ustcmd_send_cmd("trace_start", pid, NULL);
772030fe 218 if (result) {
ab33e65c
PP
219 return USTCMD_ERR_GEN;
220 }
221
222 return 0;
223}
224
763f41e5
DS
225/**
226 * Alloc an UST trace according to a PID.
227 *
228 * @param pid Traced process ID
229 * @return 0 if successful, or error USTCMD_ERR_GEN
230 */
231int ustcmd_alloc_trace(pid_t pid)
232{
233 int result;
234
235 result = ustcmd_send_cmd("trace_alloc", pid, NULL);
236 if (result) {
237 return USTCMD_ERR_GEN;
238 }
239
240 return 0;
241}
242
ab33e65c
PP
243/**
244 * Stops an UST trace according to a PID.
245 *
246 * @param pid Traced process ID
247 * @return 0 if successful, or error USTCMD_ERR_GEN
248 */
772030fe
PMF
249int ustcmd_stop_trace(pid_t pid)
250{
251 int result;
ab33e65c 252
08230db7 253 result = ustcmd_send_cmd("trace_stop", pid, NULL);
772030fe 254 if (result) {
ab33e65c
PP
255 return USTCMD_ERR_GEN;
256 }
257
258 return 0;
259}
260
261/**
262 * Counts newlines ('\n') in a string.
263 *
264 * @param str String to search in
265 * @return Total newlines count
266 */
08230db7 267unsigned int ustcmd_count_nl(const char *str)
772030fe 268{
ab33e65c
PP
269 unsigned int i = 0, tot = 0;
270
271 while (str[i] != '\0') {
272 if (str[i] == '\n') {
273 ++tot;
274 }
275 ++i;
276 }
277
278 return tot;
279}
280
281/**
282 * Frees a CMSF array.
283 *
284 * @param cmsf CMSF array to free
285 * @return 0 if successful, or error USTCMD_ERR_ARG
286 */
08230db7 287int ustcmd_free_cmsf(struct marker_status *cmsf)
772030fe 288{
ab33e65c
PP
289 if (cmsf == NULL) {
290 return USTCMD_ERR_ARG;
291 }
292
293 unsigned int i = 0;
294 while (cmsf[i].channel != NULL) {
295 free(cmsf[i].channel);
296 free(cmsf[i].marker);
297 free(cmsf[i].fs);
298 ++i;
299 }
300 free(cmsf);
301
302 return 0;
303}
304
305/**
306 * Gets channel/marker/state/format string for a given PID.
307 *
308 * @param cmsf Pointer to CMSF array to be filled (callee allocates, caller
309 * frees with `ustcmd_free_cmsf')
310 * @param pid Targeted PID
311 * @return 0 if successful, or errors {USTCMD_ERR_ARG, USTCMD_ERR_GEN}
312 */
08230db7 313int ustcmd_get_cmsf(struct marker_status **cmsf, const pid_t pid)
772030fe 314{
08230db7 315 char *big_str = NULL;
ef290fca 316 int result;
08230db7 317 struct marker_status *tmp_cmsf = NULL;
ef290fca
PMF
318 unsigned int i = 0, cmsf_ind = 0;
319
ab33e65c
PP
320 if (cmsf == NULL) {
321 return USTCMD_ERR_ARG;
322 }
08230db7 323 result = ustcmd_send_cmd("list_markers", pid, &big_str);
ef290fca 324 if (result) {
ab33e65c
PP
325 return USTCMD_ERR_GEN;
326 }
327
328 if (big_str == NULL) {
329 fprintf(stderr, "ustcmd: error while getting markers list\n");
330 return USTCMD_ERR_GEN;
331 }
332
08230db7 333 tmp_cmsf = (struct marker_status *) malloc(sizeof(struct marker_status) *
ab33e65c
PP
334 (ustcmd_count_nl(big_str) + 1));
335 if (tmp_cmsf == NULL) {
336 return USTCMD_ERR_GEN;
337 }
338
77957c95 339 /* Parse received reply string (format: "[chan]/[mark] [st] [fs]"): */
ab33e65c 340 while (big_str[i] != '\0') {
ab33e65c 341 char state;
ef290fca 342
264f6231 343 sscanf(big_str + i, "marker: %a[^/]/%a[^ ] %c %a[^\n]",
ab33e65c
PP
344 &tmp_cmsf[cmsf_ind].channel,
345 &tmp_cmsf[cmsf_ind].marker,
346 &state,
347 &tmp_cmsf[cmsf_ind].fs);
348 tmp_cmsf[cmsf_ind].state = (state == USTCMD_MS_CHR_ON ?
77957c95 349 USTCMD_MS_ON : USTCMD_MS_OFF); /* Marker state */
ab33e65c
PP
350
351 while (big_str[i] != '\n') {
77957c95 352 ++i; /* Go to next '\n' */
ab33e65c 353 }
77957c95 354 ++i; /* Skip current pointed '\n' */
ab33e65c
PP
355 ++cmsf_ind;
356 }
357 tmp_cmsf[cmsf_ind].channel = NULL;
358 tmp_cmsf[cmsf_ind].marker = NULL;
359 tmp_cmsf[cmsf_ind].fs = NULL;
360
361 *cmsf = tmp_cmsf;
362
363 free(big_str);
364 return 0;
365}
366
367/**
368 * Shoots a given command using ustcomm.
369 *
370 * @param cmd Null-terminated command to shoot
371 * @param pid Targeted PID
372 * @param reply Pointer to string to be filled with a reply string (must
373 * be NULL if no reply is needed for the given command).
374 * @return 0 if successful, or errors {USTCMD_ERR_ARG, USTCMD_ERR_CONN}
375 */
772030fe 376
08230db7 377int ustcmd_send_cmd(const char *cmd, const pid_t pid, char **reply)
772030fe
PMF
378{
379 struct ustcomm_connection conn;
380
ab33e65c
PP
381 if (cmd == NULL) {
382 return USTCMD_ERR_ARG;
383 }
384
ab33e65c 385 if (ustcomm_connect_app(pid, &conn)) {
08230db7 386 fprintf(stderr, "ustcmd_send_cmd: could not connect to PID %u\n",
ab33e65c
PP
387 (unsigned int) pid);
388 return USTCMD_ERR_CONN;
389 }
390
391 ustcomm_send_request(&conn, cmd, reply);
392
393 return 0;
394}
This page took 0.040221 seconds and 4 git commands to generate.