bb14b23f83db1fc569ca96d576185beb77408f1d
[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         if (path[0] == '/')
76             snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
77         else
78         {
79             if (pMod->cwd)
80                 snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
81             else
82                 snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
83         }
84     }
85
86     log_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
87     if (log_fd < 0)
88     {
89         XDBG_REPLY ("failed: open file(%s)\n", fd_name);
90         return FALSE;
91     }
92
93     fflush (stderr);
94     close (STDERR_FILENO);
95     dup2 (log_fd, STDERR_FILENO);
96     close (log_fd);
97
98     if (pMod->real_log_path)
99         free (pMod->real_log_path);
100
101     pMod->real_log_path = strdup (fd_name);
102     XDBG_RETURN_VAL_IF_FAIL (pMod->real_log_path != NULL, FALSE);
103
104     XDBG_REPLY ("log path: %s\n", pMod->real_log_path);
105
106     return TRUE;
107 }
108
109
110 static void
111 _CommandLogPath (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
112 {
113     if (argc != 3)
114     {
115         XDBG_REPLY ("log path: %s\n", (pMod->real_log_path)?pMod->real_log_path:"stderr");
116         return;
117     }
118
119     _CommandSetLogFile (pid, argv[2], reply, len, pMod);
120 }
121
122 static void
123 _CommandSetLogLevel (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
124 {
125     Bool ret;
126     char *module_name;
127     int level;
128
129     if (argc < 4)
130     {
131         xDbgLogEnumModules (MODE_WITH_STATUS, reply, len);
132         return;
133     }
134
135     module_name = argv[2];
136     level = atoi (argv[3]);
137
138     if (level < 0 || level >= 5)
139     {
140         XDBG_REPLY ("Error : Not valid log level %d.\n", level);
141         return;
142     }
143
144     ret = xDbgLogSetLevel (xDbgLogGetModule (module_name), level);
145
146     if (ret)
147         XDBG_REPLY ("Log level for module %s was successfully set to %d\n",
148                   module_name, level);
149     else
150         XDBG_REPLY ("Error : An error was occured during log level setting\n");
151 }
152
153 static void
154 _CommandClientList (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
155 {
156     if (argc != 2)
157     {
158         XDBG_REPLY ("Error : too few arguments\n");
159         return;
160     }
161
162     xDbgModuleCList (pMod, reply, len);
163 }
164
165 static void
166 _CommandPixmapList (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
167 {
168     if (argc != 2)
169     {
170         XDBG_REPLY ("Error : too few arguments\n");
171         return;
172     }
173
174     xDbgModulePList (pMod, reply, len);
175 }
176
177 static void
178 _CommandEvlog (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
179 {
180     int on;
181
182     if (argc != 3)
183     {
184         XDBG_REPLY ("Error : too few arguments\n");
185         return;
186     }
187
188     on = atoi (argv[2]);
189
190     xDbgModuleEvlogPrintEvents (pMod, on, argv[0], reply, len);
191
192     XDBG_REPLY ("Success\n");
193 }
194
195 static void
196 _CommandSetEvlogRule (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
197 {
198     if (argc < 2)
199     {
200         XDBG_REPLY ("Error : invalid number of arguments.\n");
201         return;
202     }
203
204     xDbgModuleEvlogInfoSetRule (pMod, argc - 2, (const char**)&(argv[2]), reply, len);
205 }
206
207 static void
208 _CommandSetEvlogPath (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
209 {
210     if (argc != 3)
211     {
212         XDBG_REPLY ("evlog path: %s\n", (pMod->evlog_path)?pMod->evlog_path:"none");
213         return;
214     }
215
216     if (!argv[2] || strlen (argv[2]) <= 0)
217     {
218         XDBG_REPLY ("invalid option\n");
219         return;
220     }
221
222     if (pMod->evlog_path)
223     {
224         free (pMod->evlog_path);
225         pMod->evlog_path=NULL;
226     }
227
228     if (!xDbgModuleEvlogSetEvlogPath (pMod, pid, argv[2], reply, len))
229     {
230         XDBG_REPLY ("Error: evlog path(%s)\n", argv[2]);
231         return;
232     }
233
234     pMod->evlog_path = strdup (argv[2]);
235
236     if (pMod->evlog_path[0] == '/')
237         XDBG_REPLY ("evlog path: %s\n", pMod->evlog_path);
238     else
239         XDBG_REPLY ("evlog path: %s/%s\n", pMod->cwd, pMod->evlog_path);
240 }
241
242 static void
243 _CommandDrmEventPending (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
244 {
245     if (argc != 2)
246     {
247         XDBG_REPLY ("Error : too few arguments\n");
248         return;
249     }
250
251     xDbgModuleDrmEventPending (pMod, reply, len);
252 }
253
254 static void
255 _CommandFpsDebug (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod)
256 {
257     int on;
258
259     if (argc != 3)
260     {
261         XDBG_REPLY ("Error : too few arguments\n");
262         return;
263     }
264
265     on = atoi (argv[2]);
266
267     xDbgModuleFpsDebug (pMod, on, reply, len);
268
269     XDBG_REPLY ("Success\n");
270 }
271
272 static struct
273 {
274     const char *Cmd;
275     const char *Description;
276     const char *Options;
277
278     int       (*DynamicUsage) (int, char*, int *);
279     const char *DetailedUsage;
280
281     void (*func) (int pid, int argc, char **argv, char *reply, int *len, XDbgModule *pMod);
282 } command_proc[] =
283 {
284     {
285         "log_path", "to set log path", "[console/filepath]",
286         NULL, "[console/filepath]",
287         _CommandLogPath
288     },
289
290     {
291         "log", "to set loglevel", "[MODULE] [0-4]",
292         (int(*)(int, char*, int*))xDbgLogEnumModules, "[DEBUG:0/TRACE:1/INFO:2/WARNING:3/ERROR:4]",
293         _CommandSetLogLevel
294     },
295
296     {
297         "clist", "to print clients", "",
298         NULL, "",
299         _CommandClientList
300     },
301
302     {
303         "plist", "to print pixmap list", "",
304         NULL, "",
305         _CommandPixmapList
306     },
307
308     {
309         "evlog", "to print x events", "[0-1]",
310         NULL, "[OFF:0/ON:1]",
311         _CommandEvlog
312     },
313
314     {
315         "evlog_rule", "to set evlog rules", "[add/remove/print]",
316         NULL, "[add allow/deny rules / remove (index) / print]",
317         _CommandSetEvlogRule
318     },
319
320     {
321         "evlog_path", "to set filepath of evlog", "[console/filepath]",
322         NULL, "[console/filepath]",
323         _CommandSetEvlogPath
324     },
325
326     {
327         "drmevent_pending", "to print pending drmvents", "",
328         NULL, "",
329         _CommandDrmEventPending
330     },
331
332     {
333         "fpsdebug", "to print fps", "[0-1]",
334         NULL, "[OFF:0/ON:1]",
335         _CommandFpsDebug
336     },
337 };
338
339 static void _CommandPrintUsage (char *reply, int *len, const char * exec)
340 {
341     int option_cnt = sizeof (command_proc) / sizeof (command_proc[0]);
342     int i;
343
344     XDBG_REPLY ("Usage : %s [cmd] [options]\n", exec);
345     XDBG_REPLY ("     ex)\n");
346
347     for (i=0; i<option_cnt; i++)
348         XDBG_REPLY ("           %s %s %s\n", exec, command_proc[i].Cmd, command_proc[i].Options);
349
350     XDBG_REPLY (" options :\n");
351
352     for (i=0; i<option_cnt; i++)
353     {
354         if (command_proc[i].Cmd && command_proc[i].Description)
355             XDBG_REPLY ("  %s (%s)\n", command_proc[i].Cmd, command_proc[i].Description);
356         else
357             XDBG_REPLY ("  Cmd(%p) or Descriptiont(%p).\n", command_proc[i].Cmd, command_proc[i].Description);
358
359         if (command_proc[i].DynamicUsage)
360         {
361             char dyn[1024];
362             int  dynlen = sizeof (dyn);
363             command_proc[i].DynamicUsage (MODE_NAME_ONLY, dyn, &dynlen);
364             XDBG_REPLY ("     [MODULE:%s]\n", dyn);
365         }
366
367         if (command_proc[i].DetailedUsage)
368             XDBG_REPLY ("     %s\n", command_proc[i].DetailedUsage);
369         else
370             XDBG_REPLY ("  DetailedUsage(%p).\n", command_proc[i].DetailedUsage);
371     }
372 }
373
374 void
375 xDbgModuleCommand (void *data, int argc, char **argv, char *reply, int *len)
376 {
377     XDbgModule *pMod = (XDbgModule*)data;
378     int nproc = sizeof (command_proc) / sizeof (command_proc[0]);
379     int i, pid, new_argc;
380     char **new_argv;
381
382     pid = atoi (argv[0]);
383     pMod->cwd = strdup (argv[1]);
384
385     new_argc = argc - 2;
386     new_argv = (char**)malloc (new_argc * sizeof (char*));
387     if (!new_argv)
388     {
389         XDBG_REPLY ("Error : malloc new_argv\n");
390         return;
391     }
392
393     for (i = 0; i < new_argc; i++)
394         new_argv[i] = argv[i+2];
395
396     if (argc < 4)
397     {
398         _CommandPrintUsage (reply, len, new_argv[0]);
399         free (new_argv);
400         return;
401     }
402
403     for (i = 0; i < nproc; i++)
404     {
405         if (!strcmp (new_argv[1], command_proc[i].Cmd) ||
406             (new_argv[1][0] == '-' && !strcmp (1 + new_argv[1], command_proc[i].Cmd)))
407         {
408             command_proc[i].func (pid, new_argc, new_argv, reply, len, pMod);
409             free (new_argv);
410             return;
411         }
412     }
413
414     _CommandPrintUsage (reply, len, new_argv[0]);
415
416     free (new_argv);
417 }
418
419 Bool
420 xDbgModuleCommandInitLogPath (XDbgModule *pMod)
421 {
422     char reply[1024];
423     int len = sizeof (reply);
424
425     if (pMod->log_path && strlen (pMod->log_path) > 0)
426     {
427         char newname[XDBG_PATH_MAX];
428         char filename[XDBG_PATH_MAX];
429         struct stat status;
430         char *p = NULL, *last = NULL;
431         int i;
432
433         snprintf (newname, XDBG_PATH_MAX, "%s", pMod->log_path);
434
435         for (i = 0; i < strlen (newname); i++)
436         {
437             p = newname + i;
438             if (*p == '/')
439                 last = p;
440         }
441
442         snprintf (filename, XDBG_PATH_MAX, "%s", last + 1);
443         snprintf (last, XDBG_PATH_MAX - (last - newname), "/prev.%s", filename);
444
445         if (!stat (pMod->log_path, &status))
446         {
447             if (rename (pMod->log_path, newname))
448             {
449                 XDBG_ERROR (MXDBG, "Failed: rename %s -> %s\n", pMod->log_path, newname);
450                 return FALSE;
451             }
452         }
453     }
454
455     if (pMod->log_path)
456         _CommandSetLogFile (0, pMod->log_path, reply, &len, pMod);
457     else
458         _CommandSetLogFile (0, "console", reply, &len, pMod);
459
460     return TRUE;
461 }