* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#define _GNU_SOURCE
#define _LGPL_SOURCE
#include <ctype.h>
#include <popt.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <assert.h>
#include <urcu/list.h>
{ 0, 0, 0, 0, 0, 0, 0, },
};
-/*
- * usage
- */
-static void usage(FILE *ofp, const char *cmd_str)
-{
- fprintf(ofp, "usage: lttng %s [-k|-u] [OPTIONS]\n", cmd_str);
- fprintf(ofp, "\n");
- fprintf(ofp, "If no session is given (-s), the context is added to\n");
- fprintf(ofp, "the current sesssion. Exactly one domain (-k or -u)\n");
- fprintf(ofp, "must be specified.\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Options:\n");
- fprintf(ofp, " -h, --help Show this help.\n");
- fprintf(ofp, " --list-options Simple listing of options.\n");
- fprintf(ofp, " -s, --session NAME Apply to session name.\n");
- fprintf(ofp, " -k, --kernel Apply to the kernel tracer.\n");
- fprintf(ofp, " -u, --userspace Apply to the user-space tracer.\n");
- fprintf(ofp, " -p, --pid [PID] Process ID tracker. Leave PID empty when used with --all.\n");
- fprintf(ofp, " -a, --all All PIDs (use with --pid).\n");
- fprintf(ofp, "\n");
-}
-
static
int parse_pid_string(const char *_pid_string,
int all, int **_pid_list, int *nr_pids)
goto error;
}
if (all) {
- pid_list = zmalloc(sizeof(*_pid_list));
+ pid_list = zmalloc(sizeof(*pid_list));
if (!pid_list) {
ERR("Out of memory");
retval = CMD_ERROR;
goto error;
}
- /* Copy */
+ /* Reparse string and populate the pid list. */
count = 0;
one_pid_str = strtok_r(pid_string, ",", &iter);
while (one_pid_str != NULL) {
}
static
-int track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str,
+enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str,
const char *session_name, const char *pid_string,
int all, struct mi_writer *writer)
{
- int ret, retval = CMD_SUCCESS, success = 1 , i;
+ int ret, success = 1 , i;
+ enum cmd_error_code retval = CMD_SUCCESS;
int *pid_list = NULL;
int nr_pids;
struct lttng_domain dom;
struct lttng_handle *handle = NULL;
- int (*lib_func)(struct lttng_handle *handle, int pid);
+ int (*cmd_func)(struct lttng_handle *handle, int pid);
switch (cmd_type) {
case CMD_TRACK:
- lib_func = lttng_track_pid;
+ cmd_func = lttng_track_pid;
break;
case CMD_UNTRACK:
- lib_func = lttng_untrack_pid;
+ cmd_func = lttng_untrack_pid;
break;
default:
ERR("Unknown command");
} else if (opt_userspace) {
dom.type = LTTNG_DOMAIN_UST;
} else {
- print_missing_domain();
- ret = CMD_ERROR;
- goto end;
+ /* Checked by the caller. */
+ assert(0);
}
ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids);
if (ret != CMD_SUCCESS) {
ERR("Error parsing PID string");
- usage(stderr, cmd_str);
retval = CMD_ERROR;
goto end;
}
for (i = 0; i < nr_pids; i++) {
DBG("%s PID %d", cmd_str, pid_list[i]);
- ret = lib_func(handle, pid_list[i]);
+ ret = cmd_func(handle, pid_list[i]);
if (ret) {
- success = 0;
- retval = CMD_ERROR;
+ switch (-ret) {
+ case LTTNG_ERR_PID_TRACKED:
+ WARN("PID %i already tracked in session %s",
+ pid_list[i], session_name);
+ success = 1;
+ retval = CMD_SUCCESS;
+ break;
+ case LTTNG_ERR_PID_NOT_TRACKED:
+ WARN("PID %i not tracked in session %s",
+ pid_list[i], session_name);
+ success = 1;
+ retval = CMD_SUCCESS;
+ break;
+ default:
+ ERR("%s", lttng_strerror(ret));
+ success = 0;
+ retval = CMD_ERROR;
+ break;
+ }
} else {
+ if (pid_list[i] != -1) {
+ MSG("PID %i %sed in session %s",
+ pid_list[i], cmd_str,
+ session_name);
+ } else {
+ MSG("All PIDs %sed in session %s",
+ cmd_str, session_name);
+ }
success = 1;
}
*/
static
int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str,
- int argc, const char **argv)
+ int argc, const char **argv, const char *help_msg)
{
- int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
+ int opt, ret = 0;
+ enum cmd_error_code command_ret = CMD_SUCCESS;
int success = 1;
static poptContext pc;
char *session_name = NULL;
struct mi_writer *writer = NULL;
if (argc < 1) {
- usage(stderr, cmd_str);
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
while ((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case OPT_HELP:
- usage(stdout, cmd_str);
+ SHOW_HELP();
goto end;
case OPT_LIST_OPTIONS:
list_cmd_options(stdout, long_options);
opt_pid = 1;
break;
default:
- usage(stderr, cmd_str);
- ret = CMD_UNDEFINED;
+ command_ret = CMD_UNDEFINED;
goto end;
}
}
- if (!(opt_userspace ^ opt_kernel)) {
- ERR("Exactly one of -u or -k needs to be specified.");
- usage(stderr, cmd_str);
- ret = CMD_ERROR;
+ ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace);
+ if (ret) {
+ command_ret = CMD_ERROR;
goto end;
}
if (!opt_session_name) {
session_name = get_session_name();
if (session_name == NULL) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
} else {
/* Currently only PID tracker is supported */
if (!opt_pid) {
ERR("Please specify at least one tracker with its expected arguments");
- usage(stderr, cmd_str);
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
if (lttng_opt_mi) {
writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
if (!writer) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
}
ret = mi_lttng_writer_command_open(writer,
get_mi_element_command(cmd_type));
if (ret) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
ret = mi_lttng_writer_open_element(writer,
mi_lttng_element_command_output);
if (ret) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
}
command_ret = track_untrack_pid(cmd_type,
cmd_str, session_name, opt_pid_string,
opt_all, writer);
- if (command_ret) {
+ if (command_ret != CMD_SUCCESS) {
success = 0;
}
/* Close output element */
ret = mi_lttng_writer_close_element(writer);
if (ret) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
ret = mi_lttng_writer_write_element_bool(writer,
mi_lttng_element_command_success, success);
if (ret) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
/* Command element close */
ret = mi_lttng_writer_command_close(writer);
if (ret) {
- ret = CMD_ERROR;
+ command_ret = CMD_ERROR;
goto end;
}
}
/* Mi clean-up */
if (writer && mi_lttng_writer_destroy(writer)) {
/* Preserve original error code */
- ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
+ command_ret = CMD_ERROR;
}
- /* Overwrite ret if an error occurred during track() */
- ret = command_ret ? command_ret : ret;
-
poptFreeContext(pc);
- return ret;
+ return (int) command_ret;
}
int cmd_track(int argc, const char **argv)
{
- return cmd_track_untrack(CMD_TRACK, "track", argc, argv);
+ static const char *help_msg =
+#ifdef LTTNG_EMBED_HELP
+#include <lttng-track.1.h>
+#else
+ NULL
+#endif
+ ;
+
+ return cmd_track_untrack(CMD_TRACK, "track", argc, argv, help_msg);
}
int cmd_untrack(int argc, const char **argv)
{
- return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv);
+ static const char *help_msg =
+#ifdef LTTNG_EMBED_HELP
+#include <lttng-untrack.1.h>
+#else
+ NULL
+#endif
+ ;
+
+ return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv, help_msg);
}