1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 */
6 #include <stdio.h>
7 #include <string.h>
8 #include <getopt.h>
9 #include <unistd.h>
10 #include <dirent.h>
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <sys/syscall.h>
14
15 #include "trace-local.h"
16
17 int silence_warnings;
18 int show_status;
19
20 #ifndef gettid
21 #define gettid() syscall(__NR_gettid)
22 #endif
23
warning(const char * fmt,...)24 void warning(const char *fmt, ...)
25 {
26 va_list ap;
27
28 if (silence_warnings)
29 return;
30
31 if (errno)
32 perror("trace-cmd");
33 errno = 0;
34
35 va_start(ap, fmt);
36 fprintf(stderr, " ");
37 vfprintf(stderr, fmt, ap);
38 va_end(ap);
39
40 fprintf(stderr, "\n");
41 }
42
malloc_or_die(unsigned int size)43 void *malloc_or_die(unsigned int size)
44 {
45 void *data;
46
47 data = malloc(size);
48 if (!data)
49 die("malloc");
50 return data;
51 }
52
53 /* Same as strtok_r(), but allows empty tokens */
strparse(char * str,char delim,char ** save)54 char *strparse(char *str, char delim, char **save)
55 {
56 char *next;
57
58 if (!str) {
59 str = *save;
60 if ((*save)[0] == '\0')
61 return NULL;
62 }
63
64 next = strchr(str, delim);
65 if (next) {
66 *next = '\0';
67 *save = next + 1;
68 } else {
69 *save = str + strlen(str);
70 }
71 return str;
72 }
73
tracecmd_debug(const char * fmt,...)74 void tracecmd_debug(const char *fmt, ...)
75 {
76 va_list ap;
77
78 if (!tracecmd_get_debug())
79 return;
80
81 va_start(ap, fmt);
82 printf("[%d] ", (int)gettid());
83 vprintf(fmt, ap);
84 va_end(ap);
85 }
86
87 static struct trace_log_severity {
88 int id;
89 const char *name;
90 } log_severity[] = {
91 { .id = TEP_LOG_NONE, .name = "none" },
92 { .id = TEP_LOG_CRITICAL, .name = "crit" },
93 { .id = TEP_LOG_ERROR, .name = "err" },
94 { .id = TEP_LOG_WARNING, .name = "warn" },
95 { .id = TEP_LOG_INFO, .name = "info" },
96 { .id = TEP_LOG_DEBUG, .name = "debug" },
97 { .id = TEP_LOG_ALL, .name = "all" },
98 };
99
trace_set_loglevel(int level)100 void trace_set_loglevel(int level)
101 {
102 tracecmd_set_loglevel(level);
103 tracefs_set_loglevel(level);
104 tep_set_loglevel(level);
105 }
106
trace_set_verbose(char * level)107 int trace_set_verbose(char *level)
108 {
109 int id;
110
111 /* Default level is info */
112 if (!level)
113 level = "info";
114
115 if (isdigit(level[0])) {
116 id = atoi(level);
117 if (id >= TEP_LOG_NONE) {
118 if (id > TEP_LOG_ALL)
119 id = TEP_LOG_ALL;
120 trace_set_loglevel(id);
121 return 0;
122 }
123 } else {
124 int size = ARRAY_SIZE(log_severity);
125 int i;
126
127 for (i = 0; i < size; i++) {
128 if (!strncmp(level, log_severity[i].name, strlen(log_severity[i].name))) {
129 trace_set_loglevel(log_severity[i].id);
130 return 0;
131 }
132 }
133 }
134
135 return -1;
136 }
137
138 /**
139 * struct command
140 * @name command name
141 * @run function to execute on command `name`
142 */
143 struct command {
144 char *name;
145 void (*run)(int argc, char **argv);
146 };
147
148
149 /**
150 * Lookup table that maps command names to functions
151 */
152 struct command commands[] = {
153 {"report", trace_report},
154 {"snapshot", trace_snapshot},
155 {"hist", trace_hist},
156 {"mem", trace_mem},
157 {"listen", trace_listen},
158 {"agent", trace_agent},
159 {"setup-guest", trace_setup_guest},
160 {"split", trace_split},
161 {"restore", trace_restore},
162 {"stack", trace_stack},
163 {"check-events", trace_check_events},
164 {"record", trace_record},
165 {"start", trace_start},
166 {"set", trace_set},
167 {"extract", trace_extract},
168 {"stop", trace_stop},
169 {"stream", trace_stream},
170 {"profile", trace_profile},
171 {"restart", trace_restart},
172 {"clear", trace_clear},
173 {"reset", trace_reset},
174 {"stat", trace_stat},
175 {"options", trace_option},
176 {"show", trace_show},
177 {"list", trace_list},
178 {"help", trace_usage},
179 {"dump", trace_dump},
180 {"attach", trace_attach},
181 {"convert", trace_convert},
182 {"sqlhist", trace_sqlhist},
183 {"-h", trace_usage},
184 };
185
main(int argc,char ** argv)186 int main (int argc, char **argv)
187 {
188 int i;
189
190 errno = 0;
191
192 if (argc < 2)
193 trace_usage(argc, argv);
194
195 for (i = 0; i < ARRAY_SIZE(commands); ++i) {
196 if (strcmp(argv[1], commands[i].name) == 0 ){
197 commands[i].run(argc, argv);
198 goto out;
199 }
200 }
201
202 /* No valid command found, show help */
203 trace_usage(argc, argv);
204 out:
205 exit(0);
206 }
207