1 /* Copyright (C) 2009 Pierre-Marc Fournier, Philippe Proulx-Barrette
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.
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.
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
28 #include "ust/ustcmd.h"
31 pid_t
*ustcmd_get_online_pids(void)
33 struct dirent
*dirent
;
35 unsigned int ret_size
= 1 * sizeof(pid_t
), i
= 0;
37 dir
= opendir(SOCK_DIR
);
42 pid_t
*ret
= (pid_t
*) malloc(ret_size
);
44 while ((dirent
= readdir(dir
))) {
45 if (!strcmp(dirent
->d_name
, ".") ||
46 !strcmp(dirent
->d_name
, "..")) {
51 if (dirent
->d_type
!= DT_DIR
&&
52 !!strcmp(dirent
->d_name
, "ustd")) {
54 sscanf(dirent
->d_name
, "%u", (unsigned int *) &ret
[i
]);
55 /* FIXME: Here we previously called pid_is_online, which
56 * always returned 1, now I replaced it with just 1.
57 * We need to figure out an intelligent way of solving
58 * this, maybe connect-disconnect.
61 ret_size
+= sizeof(pid_t
);
62 ret
= (pid_t
*) realloc(ret
, ret_size
);
68 ret
[i
] = 0; /* Array end */
81 * Sets marker state (USTCMD_MS_ON or USTCMD_MS_OFF).
83 * @param mn Marker name
84 * @param state Marker's new state
85 * @param pid Traced process ID
86 * @return 0 if successful, or errors {USTCMD_ERR_GEN, USTCMD_ERR_ARG}
88 int ustcmd_set_marker_state(const char *mn
, int state
, pid_t pid
)
90 char *cmd_str
[] = {"disable_marker", "enable_marker"};
95 return USTCMD_ERR_ARG
;
98 if (asprintf(&cmd
, "%s %s", cmd_str
[state
], mn
) < 0) {
99 ERR("ustcmd_set_marker_state : asprintf failed (%s %s)",
101 return USTCMD_ERR_GEN
;
104 result
= ustcmd_send_cmd(cmd
, pid
, NULL
);
107 return USTCMD_ERR_GEN
;
115 * Set subbuffer size.
117 * @param channel_size Channel name and size
118 * @param pid Traced process ID
119 * @return 0 if successful, or error
121 int ustcmd_set_subbuf_size(const char *channel_size
, pid_t pid
)
126 if (asprintf(&cmd
, "%s %s", "set_subbuf_size", channel_size
) < 0) {
127 ERR("ustcmd_set_subbuf_size : asprintf failed (set_subbuf_size %s)",
132 result
= ustcmd_send_cmd(cmd
, pid
, NULL
);
145 * @param channel_num Channel name and num
146 * @param pid Traced process ID
147 * @return 0 if successful, or error
149 int ustcmd_set_subbuf_num(const char *channel_size
, pid_t pid
)
154 if (asprintf(&cmd
, "%s %s", "set_subbuf_num", channel_size
) < 0) {
155 ERR("ustcmd_set_subbuf_num : asprintf failed (set_subbuf_num %s",
160 result
= ustcmd_send_cmd(cmd
, pid
, NULL
);
171 * Get subbuffer size.
173 * @param channel Channel name
174 * @param pid Traced process ID
175 * @return subbuf size if successful, or error
177 int ustcmd_get_subbuf_size(const char *channel
, pid_t pid
)
182 /* format: channel_cpu */
183 if (asprintf(&cmd
, "%s %s_0", "get_subbuf_size", channel
) < 0) {
184 ERR("ustcmd_get_subbuf_size : asprintf failed (get_subbuf_size, %s_0",
189 result
= ustcmd_send_cmd(cmd
, pid
, &reply
);
195 result
= atoi(reply
);
204 * @param channel Channel name
205 * @param pid Traced process ID
206 * @return subbuf cnf if successful, or error
208 int ustcmd_get_subbuf_num(const char *channel
, pid_t pid
)
213 /* format: channel_cpu */
214 if (asprintf(&cmd
, "%s %s_0", "get_n_subbufs", channel
) < 0) {
215 ERR("ustcmd_get_subbuf_num : asprintf failed (get_n_subbufs, %s_0",
220 result
= ustcmd_send_cmd(cmd
, pid
, &reply
);
226 result
= atoi(reply
);
233 * Destroys an UST trace according to a PID.
235 * @param pid Traced process ID
236 * @return 0 if successful, or error USTCMD_ERR_GEN
238 int ustcmd_destroy_trace(pid_t pid
)
242 result
= ustcmd_send_cmd("trace_destroy", pid
, NULL
);
244 return USTCMD_ERR_GEN
;
251 * Starts an UST trace (and setups it) according to a PID.
253 * @param pid Traced process ID
254 * @return 0 if successful, or error USTCMD_ERR_GEN
256 int ustcmd_setup_and_start(pid_t pid
)
260 result
= ustcmd_send_cmd("start", pid
, NULL
);
262 return USTCMD_ERR_GEN
;
269 * Creates an UST trace according to a PID.
271 * @param pid Traced process ID
272 * @return 0 if successful, or error USTCMD_ERR_GEN
274 int ustcmd_create_trace(pid_t pid
)
278 result
= ustcmd_send_cmd("trace_create", pid
, NULL
);
280 return USTCMD_ERR_GEN
;
287 * Starts an UST trace according to a PID.
289 * @param pid Traced process ID
290 * @return 0 if successful, or error USTCMD_ERR_GEN
292 int ustcmd_start_trace(pid_t pid
)
296 result
= ustcmd_send_cmd("trace_start", pid
, NULL
);
298 return USTCMD_ERR_GEN
;
305 * Alloc an UST trace according to a PID.
307 * @param pid Traced process ID
308 * @return 0 if successful, or error USTCMD_ERR_GEN
310 int ustcmd_alloc_trace(pid_t pid
)
314 result
= ustcmd_send_cmd("trace_alloc", pid
, NULL
);
316 return USTCMD_ERR_GEN
;
323 * Stops an UST trace according to a PID.
325 * @param pid Traced process ID
326 * @return 0 if successful, or error USTCMD_ERR_GEN
328 int ustcmd_stop_trace(pid_t pid
)
332 result
= ustcmd_send_cmd("trace_stop", pid
, NULL
);
334 return USTCMD_ERR_GEN
;
341 * Counts newlines ('\n') in a string.
343 * @param str String to search in
344 * @return Total newlines count
346 unsigned int ustcmd_count_nl(const char *str
)
348 unsigned int i
= 0, tot
= 0;
350 while (str
[i
] != '\0') {
351 if (str
[i
] == '\n') {
361 * Frees a CMSF array.
363 * @param cmsf CMSF array to free
364 * @return 0 if successful, or error USTCMD_ERR_ARG
366 int ustcmd_free_cmsf(struct marker_status
*cmsf
)
369 return USTCMD_ERR_ARG
;
373 while (cmsf
[i
].channel
!= NULL
) {
374 free(cmsf
[i
].channel
);
375 free(cmsf
[i
].marker
);
385 * Gets channel/marker/state/format string for a given PID.
387 * @param cmsf Pointer to CMSF array to be filled (callee allocates, caller
388 * frees with `ustcmd_free_cmsf')
389 * @param pid Targeted PID
390 * @return 0 if successful, or -1 on error
392 int ustcmd_get_cmsf(struct marker_status
**cmsf
, const pid_t pid
)
394 char *big_str
= NULL
;
396 struct marker_status
*tmp_cmsf
= NULL
;
397 unsigned int i
= 0, cmsf_ind
= 0;
402 result
= ustcmd_send_cmd("list_markers", pid
, &big_str
);
404 ERR("error while getting markers list");
408 tmp_cmsf
= (struct marker_status
*) malloc(sizeof(struct marker_status
) *
409 (ustcmd_count_nl(big_str
) + 1));
410 if (tmp_cmsf
== NULL
) {
411 ERR("Failed to allocate CMSF array");
415 /* Parse received reply string (format: "[chan]/[mark] [st] [fs]"): */
416 while (big_str
[i
] != '\0') {
419 sscanf(big_str
+ i
, "marker: %a[^/]/%a[^ ] %c %a[^\n]",
420 &tmp_cmsf
[cmsf_ind
].channel
,
421 &tmp_cmsf
[cmsf_ind
].marker
,
423 &tmp_cmsf
[cmsf_ind
].fs
);
424 tmp_cmsf
[cmsf_ind
].state
= (state
== USTCMD_MS_CHR_ON
?
425 USTCMD_MS_ON
: USTCMD_MS_OFF
); /* Marker state */
427 while (big_str
[i
] != '\n') {
428 ++i
; /* Go to next '\n' */
430 ++i
; /* Skip current pointed '\n' */
433 tmp_cmsf
[cmsf_ind
].channel
= NULL
;
434 tmp_cmsf
[cmsf_ind
].marker
= NULL
;
435 tmp_cmsf
[cmsf_ind
].fs
= NULL
;
447 * @param tes TES array to free
448 * @return 0 if successful, or error USTCMD_ERR_ARG
450 int ustcmd_free_tes(struct trace_event_status
*tes
)
453 return USTCMD_ERR_ARG
;
457 while (tes
[i
].name
!= NULL
) {
467 * Gets trace_events string for a given PID.
469 * @param tes Pointer to TES array to be filled (callee allocates, caller
470 * frees with `ustcmd_free_tes')
471 * @param pid Targeted PID
472 * @return 0 if successful, or -1 on error
474 int ustcmd_get_tes(struct trace_event_status
**tes
,
477 char *big_str
= NULL
;
479 struct trace_event_status
*tmp_tes
= NULL
;
480 unsigned int i
= 0, tes_ind
= 0;
486 result
= ustcmd_send_cmd("list_trace_events", pid
, &big_str
);
488 ERR("error while getting trace_event list");
492 tmp_tes
= (struct trace_event_status
*)
493 zmalloc(sizeof(struct trace_event_status
) *
494 (ustcmd_count_nl(big_str
) + 1));
495 if (tmp_tes
== NULL
) {
496 ERR("Failed to allocate TES array");
500 /* Parse received reply string (format: "[name]"): */
501 while (big_str
[i
] != '\0') {
504 sscanf(big_str
+ i
, "trace_event: %a[^\n]",
505 &tmp_tes
[tes_ind
].name
);
506 while (big_str
[i
] != '\n') {
507 ++i
; /* Go to next '\n' */
509 ++i
; /* Skip current pointed '\n' */
512 tmp_tes
[tes_ind
].name
= NULL
;
523 * @param sock_path Socket path
524 * @param pid Traced process ID
525 * @return 0 if successful, or error
527 int ustcmd_set_sock_path(const char *sock_path
, pid_t pid
)
532 if (asprintf(&cmd
, "%s %s", "set_sock_path", sock_path
) < 0) {
533 ERR("ustcmd_set_sock_path : asprintf failed (set_sock_path, %s",
538 result
= ustcmd_send_cmd(cmd
, pid
, NULL
);
541 return USTCMD_ERR_GEN
;
551 * @param sock_path Pointer to where the socket path will be returned
552 * @param pid Traced process ID
553 * @return 0 if successful, or error
555 int ustcmd_get_sock_path(char **sock_path
, pid_t pid
)
560 if (asprintf(&cmd
, "%s", "get_sock_path") < 0) {
561 ERR("ustcmd_get_sock_path : asprintf failed");
562 return USTCMD_ERR_GEN
;
565 result
= ustcmd_send_cmd(cmd
, pid
, &reply
);
568 return USTCMD_ERR_GEN
;
576 int ustcmd_force_switch(pid_t pid
)
580 result
= ustcmd_send_cmd("force_switch", pid
, NULL
);
582 return USTCMD_ERR_GEN
;
589 * Sends a given command to a traceable process
591 * @param cmd Null-terminated command to send
592 * @param pid Targeted PID
593 * @param reply Pointer to string to be filled with a reply string (must
594 * be NULL if no reply is needed for the given command).
595 * @return -1 if not successful, 0 on EOT, 1 on success
598 int ustcmd_send_cmd(const char *cmd
, const pid_t pid
, char **reply
)
603 if (ustcomm_connect_app(pid
, &app_fd
)) {
604 ERR("could not connect to PID %u", (unsigned int) pid
);
608 retval
= ustcomm_send_request(app_fd
, cmd
, reply
);
This page took 0.063482 seconds and 4 git commands to generate.