ed77c03accd45d2e084f68a7d873723b2b5d3f25
[adaptation/xorg/driver/xserver-xorg-module-xdbg.git] / module / xdbg_module_command.c
1 /**************************************************************************
2
3 xdbg
4
5 Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8          Sangjin LEE <lsj119@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <windowstr.h>
43 #include <xacestr.h>
44 #include <xdbg.h>
45 #include "xdbg_types.h"
46 #include <xf86Priv.h>
47 #include "xdbg_module.h"
48 #include "xdbg_module_clist.h"
49 #include "xdbg_module_plist.h"
50 #include "xdbg_module_evlog.h"
51 #include "xdbg_module_drmevent.h"
52 #include "xdbg_module_fpsdebug.h"
53 #include "xdbg_module_command.h"
54
55 static Bool
56 _CommandSetLogFile (int pid, char *path, char *reply, int *len, XDbgModule *pMod)
57 {
58     static int old_stderr = -1;
59     char fd_name[XDBG_PATH_MAX];
60     int  log_fd = -1;
61
62     if (!path || strlen (path) <= 0)
63     {
64         XDBG_REPLY ("failed: logpath is invalid\n");
65         return FALSE;
66     }
67
68     if (old_stderr == -1)
69         old_stderr = dup (STDERR_FILENO);
70
71     if (!strcmp (path, "console"))
72         snprintf (fd_name, XDBG_PATH_MAX, "/proc/%d/fd/1", pid);
73     else
74     {
75         char *temp[3] = {"/", "./", "../"};
76         Bool valid = FALSE;
77         int i;
78
79         for (i = 0; i < sizeof (temp) / sizeof (char*); i++)
80             if (path == strstr (path, temp[i]))
81             {
82                 valid = TRUE;
83                 break;
84             }
85
86         if (valid)
87         {
88             if (path[0] == '/')
89                 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
90             else
91             {
92                 char cwd[128];
93                 if (getcwd (cwd, sizeof (cwd)))
94                     snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", cwd, path);
95                 else
96                     snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
97             }
98         }
99         else
100         {
101             XDBG_REPLY ("failed: invalid option(%s)\n", path);
102             return FALSE;
103         }
104     }
105
106     log_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
107     if (log_fd < 0)
108     {
109         XDBG_REPLY ("failed: open file(%s)\n", fd_name);
110         return FALSE;
111     }
112
113     fflush (stderr);
114     close (STDERR_FILENO);
115     dup2 (log_fd, STDERR_FILENO);
116     close (log_fd);
117
118     if (pMod->real_log_path)
119         free (pMod->real_log_path);
120
121     pMod->real_log_path = strdup (fd_name);
122     XDBG_RETURN_VAL_IF_FAIL (pMod->real_log_path != NULL, FALSE);
123
124     XDBG_REPLY ("log path: %s\n", pMod->real_log_path);
125
126     return TRUE;
127 }
128
129
130 static void
131 _CommandLogPath (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
132 {
133     if (argc != 3)
134     {
135         XDBG_REPLY ("log path: %s\n", (pMod->real_log_path)?pMod->real_log_path:"stderr");
136         return;
137     }
138
139     _CommandSetLogFile (pid, argv[2], reply, len, pMod);
140 }
141
142 static void
143 _CommandSetLogLevel (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
144 {
145     Bool ret;
146     char *module_name;
147     int level;
148
149     if (argc < 4)
150     {
151         xDbgLogEnumModules (MODE_WITH_STATUS, reply, len);
152         return;
153     }
154
155     module_name = argv[2];
156     level = atoi (argv[3]);
157
158     if (level < 0 || level >= 5)
159     {
160         XDBG_REPLY ("Error : Not valid log level %d.\n", level);
161         return;
162     }
163
164     ret = xDbgLogSetLevel (xDbgLogGetModule (module_name), level);
165
166     if (ret)
167         XDBG_REPLY ("Log level for module %s was successfully set to %d\n",
168                   module_name, level);
169     else
170         XDBG_REPLY ("Error : An error was occured during log level setting\n");
171 }
172
173 static void
174 _CommandClientList (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
175 {
176     if (argc != 2)
177     {
178         XDBG_REPLY ("Error : too few arguments\n");
179         return;
180     }
181
182     xDbgModuleCList (pMod, reply, len);
183 }
184
185 static void
186 _CommandPixmapList (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
187 {
188     if (argc != 2)
189     {
190         XDBG_REPLY ("Error : too few arguments\n");
191         return;
192     }
193
194     xDbgModulePList (pMod, reply, len);
195 }
196
197 static void
198 _CommandEvlog (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
199 {
200     int on;
201
202     if (argc != 3)
203     {
204         XDBG_REPLY ("Error : too few arguments\n");
205         return;
206     }
207
208     on = atoi (argv[2]);
209
210     xDbgModuleEvlogPrintEvents (pMod, on, argv[0], reply, len);
211
212     XDBG_REPLY ("Success\n");
213 }
214
215 static void
216 _CommandSetEvlogRule (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
217 {
218     if (argc < 2)
219     {
220         XDBG_REPLY ("Error : invalid number of arguments.\n");
221         return;
222     }
223
224     xDbgModuleEvlogInfoSetRule (pMod, argc - 2, (const char**)&(argv[2]), reply, len);
225 }
226
227 static void
228 _CommandSetEvlogPath (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
229 {
230     if (argc != 3)
231     {
232         XDBG_REPLY ("evlog path: %s\n", (pMod->evlog_path)?pMod->evlog_path:"none");
233         return;
234     }
235
236     if (!argv[2] || strlen (argv[2]) <= 0)
237     {
238         XDBG_REPLY ("invalid option\n");
239         return;
240     }
241
242     if (pMod->evlog_path)
243     {
244         free (pMod->evlog_path);
245         pMod->evlog_path=NULL;
246     }
247
248     if (!xDbgModuleEvlogSetEvlogPath (pMod, pid, argv[2], reply, len))
249     {
250         XDBG_REPLY ("Error: evlog path(%s)\n", argv[2]);
251         return;
252     }
253
254     pMod->evlog_path = strdup (argv[2]);
255
256     XDBG_REPLY ("evlog path: %s\n", pMod->evlog_path);
257 }
258
259 static void
260 _CommandDrmEventPending (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
261 {
262     if (argc != 2)
263     {
264         XDBG_REPLY ("Error : too few arguments\n");
265         return;
266     }
267
268     xDbgModuleDrmEventPending (pMod, reply, len);
269 }
270
271 static void
272 _CommandFpsDebug (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
273 {
274     int on;
275
276     if (argc != 3)
277     {
278         XDBG_REPLY ("Error : too few arguments\n");
279         return;
280     }
281
282     on = atoi (argv[2]);
283
284     xDbgModuleFpsDebug (pMod, on, reply, len);
285
286     XDBG_REPLY ("Success\n");
287 }
288
289 static struct
290 {
291     const char *Cmd;
292     const char *Description;
293     const char *Options;
294
295     int       (*DynamicUsage) (int, char*, int *);
296     const char *DetailedUsage;
297
298     void (*func) (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod);
299 } command_proc[] =
300 {
301     {
302         "log_path", "to set log path", "[console/filepath]",
303         NULL, "[console/filepath]",
304         _CommandLogPath
305     },
306
307     {
308         "log", "to set loglevel", "[MODULE] [0-4]",
309         (int(*)(int, char*, int*))xDbgLogEnumModules, "[DEBUG:0/TRACE:1/INFO:2/WARNING:3/ERROR:4]",
310         _CommandSetLogLevel
311     },
312
313     {
314         "clist", "to print clients", "",
315         NULL, "",
316         _CommandClientList
317     },
318
319     {
320         "plist", "to print pixmap list", "",
321         NULL, "",
322         _CommandPixmapList
323     },
324
325     {
326         "evlog", "to print x events", "[0-1]",
327         NULL, "[OFF:0/ON:1]",
328         _CommandEvlog
329     },
330
331     {
332         "evlog_rule", "to set evlog rules", "[add/remove/print]",
333         NULL, "[add allow/deny rules / remove (index) / print]",
334         _CommandSetEvlogRule
335     },
336
337     {
338         "evlog_path", "to set filepath of evlog", "[console/filepath]",
339         NULL, "[console/filepath]",
340         _CommandSetEvlogPath
341     },
342
343     {
344         "drmevent_pending", "to print pending drmvents", "",
345         NULL, "",
346         _CommandDrmEventPending
347     },
348
349     {
350         "fpsdebug", "to print fps", "[0-1]",
351         NULL, "[OFF:0/ON:1]",
352         _CommandFpsDebug
353     },
354 };
355
356 static void _CommandPrintUsage (char *reply, int *len, const char * exec)
357 {
358     int option_cnt = sizeof (command_proc) / sizeof (command_proc[0]);
359     int i;
360
361     XDBG_REPLY ("Usage : %s [cmd] [options]\n", exec);
362     XDBG_REPLY ("     ex)\n");
363
364     for (i=0; i<option_cnt; i++)
365         XDBG_REPLY ("           %s %s %s\n", exec, command_proc[i].Cmd, command_proc[i].Options);
366
367     XDBG_REPLY (" options :\n");
368
369     for (i=0; i<option_cnt; i++)
370     {
371         if (command_proc[i].Cmd && command_proc[i].Description)
372             XDBG_REPLY ("  %s (%s)\n", command_proc[i].Cmd, command_proc[i].Description);
373         else
374             XDBG_REPLY ("  Cmd(%p) or Descriptiont(%p).\n", command_proc[i].Cmd, command_proc[i].Description);
375
376         if (command_proc[i].DynamicUsage)
377         {
378             char dyn[1024];
379             int  dynlen = sizeof (dyn);
380             command_proc[i].DynamicUsage (MODE_NAME_ONLY, dyn, &dynlen);
381             XDBG_REPLY ("     [MODULE:%s]\n", dyn);
382         }
383
384         if (command_proc[i].DetailedUsage)
385             XDBG_REPLY ("     %s\n", command_proc[i].DetailedUsage);
386         else
387             XDBG_REPLY ("  DetailedUsage(%p).\n", command_proc[i].DetailedUsage);
388     }
389 }
390
391 void
392 xDbgModuleCommand (void *data, int argc, char **argv, char *reply, int *len)
393 {
394     XDbgModule *pMod = (XDbgModule*)data;
395     int nproc = sizeof (command_proc) / sizeof (command_proc[0]);
396     int i, pid, new_argc;
397     char **new_argv;
398
399     pid = atoi (argv[0]);
400
401     new_argc = argc - 1;
402     new_argv = (char**)malloc (new_argc * sizeof (char*));
403     if (!new_argv)
404     {
405         XDBG_REPLY ("Error : malloc new_argv\n");
406         return;
407     }
408
409     for (i = 0; i < new_argc; i++)
410         new_argv[i] = argv[i+1];
411
412     if (argc < 3)
413     {
414         _CommandPrintUsage (reply, len, new_argv[0]);
415         free (new_argv);
416         return;
417     }
418
419     for (i = 0; i < nproc; i++)
420     {
421         if (!strcmp (new_argv[1], command_proc[i].Cmd) ||
422             (new_argv[1][0] == '-' && !strcmp (1 + new_argv[1], command_proc[i].Cmd)))
423         {
424             command_proc[i].func (pid, new_argc, new_argv, reply, len, pMod);
425             free (new_argv);
426             return;
427         }
428     }
429
430     _CommandPrintUsage (reply, len, new_argv[0]);
431
432     free (new_argv);
433 }
434
435 Bool
436 xDbgModuleCommandInitLogPath (XDbgModule *pMod)
437 {
438     char reply[1024];
439     int len = sizeof (reply);
440
441     if (pMod->log_path && strlen (pMod->log_path) > 0)
442     {
443         char newname[XDBG_PATH_MAX];
444         char filename[XDBG_PATH_MAX];
445         struct stat status;
446         char *p = NULL, *last = NULL;
447         int i;
448
449         snprintf (newname, XDBG_PATH_MAX, "%s", pMod->log_path);
450
451         for (i = 0; i < strlen (newname); i++)
452         {
453             p = newname + i;
454             if (*p == '/')
455                 last = p;
456         }
457
458         snprintf (filename, XDBG_PATH_MAX, "%s", last + 1);
459         snprintf (last, XDBG_PATH_MAX - (last - newname), "/prev.%s", filename);
460
461         if (!stat (pMod->log_path, &status))
462         {
463             if (rename (pMod->log_path, newname))
464             {
465                 XDBG_ERROR (MXDBG, "Failed: rename %s -> %s\n", pMod->log_path, newname);
466                 return FALSE;
467             }
468         }
469     }
470
471     if (pMod->log_path)
472         _CommandSetLogFile (0, pMod->log_path, reply, &len, pMod);
473     else
474         _CommandSetLogFile (0, "console", reply, &len, pMod);
475
476     return TRUE;
477 }