add supplementary log massage of each major extension
[platform/adaptation/xf86-module-xdbg.git] / common / xdbg_evlog.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 #include <stdio.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <sys/types.h>
36 #include <sys/fcntl.h>
37 #include <unistd.h>
38 #include <stdarg.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <time.h>
42 #include <X11/Xlib.h>
43
44 #include "xdbg_types.h"
45 #include "xdbg_evlog.h"
46 #include "bool_exp_rule_checker.h"
47
48 static char *evt_type[] = { "Event", "Request", "Reply", "Flush" };
49 static char *evt_dir[]  = { "<====", "---->",   "<----", "*****" };
50
51 static RULE_CHECKER rc = NULL;
52
53 static void
54 _mergeArgs (char * target, int argc, const char ** argv)
55 {
56     int i;
57     int len;
58
59     for (i=0; i<argc; i++)
60     {
61         len = sprintf (target, "%s", argv[i]);
62         target += len;
63
64         if (i != argc - 1)
65             *(target++) = ' ';
66     }
67 }
68
69 static int
70 _strcasecmp(const char *str1, const char *str2)
71 {
72     const u_char *us1 = (const u_char *) str1, *us2 = (const u_char *) str2;
73
74     while (tolower(*us1) == tolower(*us2)) {
75         if (*us1++ == '\0')
76             return 0;
77         us2++;
78     }
79
80     return (tolower(*us1) - tolower(*us2));
81 }
82
83 char*
84 xDbgEvlogGetCmd (char *path)
85 {
86     char *p;
87     if (!path)
88         return NULL;
89     p = strrchr (path, '/');
90     return (p)?p+1:path;
91 }
92
93 Bool
94 xDbgEvlogRuleSet (const int argc, const char **argv, char *reply, int *len)
95 {
96     const char * command;
97
98     if (rc == NULL)
99         rc = rulechecker_init();
100
101     if (argc == 0)
102     {
103         rulechecker_print_rule (rc, reply);
104         return TRUE;
105     }
106
107     command = argv[0];
108
109     if (!_strcasecmp (command, "add"))
110     {
111         POLICY_TYPE policy_type;
112         RC_RESULT_TYPE result;
113         const char * policy = argv[1];
114         char rule[8192];
115
116         if (argc < 3)
117         {
118             REPLY ("Error : Too few arguments.\n");
119             return FALSE;
120         }
121
122         if (!_strcasecmp (policy, "ALLOW"))
123             policy_type = ALLOW;
124         else if (!_strcasecmp (policy, "DENY"))
125             policy_type = DENY;
126         else
127         {
128             REPLY ("Error : Unknown policy : [%s].\n          Policy should be ALLOW or DENY.\n", policy);
129             return FALSE;
130         }
131
132         _mergeArgs (rule, argc - 2, &(argv[2]));
133
134         result = rulechecker_add_rule (rc, policy_type, rule);
135         if (result == RC_ERR_TOO_MANY_RULES)
136         {
137             REPLY ("Error : Too many rules were added.\n");
138             return FALSE;
139         }
140         else if (result == RC_ERR_PARSE_ERROR)
141         {
142             REPLY ("Error : An error occured during parsing the rule [%s]\n", rule);
143             return FALSE;
144         }
145
146         REPLY ("The rule was successfully added.\n\n");
147         rulechecker_print_rule (rc, reply);
148         return TRUE;
149     }
150     else if (!_strcasecmp (command, "remove"))
151     {
152         const char * remove_idx;
153         int i;
154
155         if (argc < 2)
156         {
157             REPLY ("Error : Too few arguments.\n");
158             return FALSE;
159         }
160
161         for (i=0; i<argc - 1; i++)
162         {
163             remove_idx = argv[i+1];
164
165             if (!_strcasecmp (remove_idx, "all"))
166             {
167                 rulechecker_destroy (rc);
168                 rc = rulechecker_init();
169                 REPLY ("Every rules were successfully removed.\n");
170             }
171             else
172             {
173                 int index = atoi (remove_idx);
174                 if (isdigit (*remove_idx) && rulechecker_remove_rule (rc, index) == 0)
175                     REPLY ("The rule [%d] was successfully removed.\n", index);
176                 else
177                     REPLY ("Rule remove fail : No such rule [%s].\n", remove_idx);
178             }
179         }
180         rulechecker_print_rule (rc, reply);
181         return TRUE;
182     }
183     else if (!_strcasecmp (command, "print"))
184     {
185         rulechecker_print_rule (rc, reply);
186         return TRUE;
187     }
188     else if (!_strcasecmp (command, "help"))
189     {
190         REPLY ("%s", rulechecker_print_usage());
191         return TRUE;
192     }
193
194     REPLY ("%s\nUnknown command : [%s].\n\n", rulechecker_print_usage(), command);
195
196     return TRUE;
197 }
198
199 Bool
200 xDbgEvlogRuleValidate (EvlogInfo *evinfo)
201 {
202     const char *evlog_name = "";
203     char *cmd = "";
204
205     if (rc == NULL)
206         rc = rulechecker_init ();
207
208     if (!rc)
209     {
210         fprintf (stderr, "failed: create rulechecker\n");
211         return FALSE;
212     }
213
214     cmd = xDbgEvlogGetCmd (evinfo->client.command);
215
216     if (evinfo->type == REQUEST)
217         evlog_name = evinfo->req.name;
218     else if (evinfo->type == EVENT)
219         evlog_name = evinfo->evt.name;
220
221     return rulechecker_validate_rule (rc,
222                                       evinfo->type,
223                                       evinfo->req.id,
224                                       evlog_name,
225                                       evinfo->client.pid,
226                                       cmd);
227 }
228
229
230 ExtensionInfo Evlog_extensions[] = {
231     {xDbgEvlogCompositeGetBase, 0, 0, 0, NULL},
232     {xDbgEvlogDamageGetBase, 0, 0, 0, NULL},
233     {xDbgEvlogDri2GetBase, 0, 0, 0, NULL},
234     {xDbgEvlogGestureGetBase, 0, 0, 0, NULL},
235     {xDbgEvlogRandrGetBase, 0, 0, 0, NULL},
236     {xDbgEvlogXextDpmsGetBase, 0, 0, 0, NULL},
237     {xDbgEvlogXextShmGetBase, 0, 0, 0, NULL},
238     {xDbgEvlogXextSyncGetBase, 0, 0, 0, NULL},
239     {xDbgEvlogXextXtestGetBase, 0, 0, 0, NULL},
240     {xDbgEvlogXextXtestExt1GetBase, 0, 0, 0, NULL},
241     {xDbgEvlogXvGetBase, 0, 0, 0, NULL}
242 };
243 ExtensionInfo* Sorted_Evlog_extensions;
244
245 static void
246 _ExtensionsSwap(ExtensionInfo* first, ExtensionInfo* second)
247 {
248     ExtensionInfo temp;
249
250     temp = *first ;
251     *first = *second ;
252     *second = temp ;
253 }
254
255 static Bool
256 _SortEvlogExtensions ()
257 {
258     int i,j;
259     int swap;
260
261     Sorted_Evlog_extensions = (ExtensionInfo*)malloc(sizeof(Evlog_extensions));
262     RETURN_VAL_IF_FAIL (Sorted_Evlog_extensions != NULL, FALSE);
263
264     memcpy(Sorted_Evlog_extensions, Evlog_extensions, sizeof(Evlog_extensions));
265
266     for (i = 0 ; i < sizeof (Evlog_extensions) / sizeof (ExtensionInfo) - 1 ; i++)
267     {
268         swap = 0;
269         for (j = 1 ; j < sizeof (Evlog_extensions) / sizeof (ExtensionInfo) - i ; j++)
270         {
271             if(Sorted_Evlog_extensions[j-1].evt_base > Sorted_Evlog_extensions[j].evt_base)
272             {
273                 _ExtensionsSwap(&Sorted_Evlog_extensions[j-1], &Sorted_Evlog_extensions[j]);
274                 swap = 1;
275             }
276         }
277         if (!swap) break;
278     }
279
280     return TRUE;
281 }
282
283
284 static Bool
285 _EvlogGetExtentionEntry (int *return_extensions_size)
286 {
287     static int init = 0;
288     static Bool success = FALSE;
289     Display *dpy = NULL;
290     int i;
291
292     if (init)
293         return success;
294
295     init = 1;
296
297 #ifdef XDBG_CLIENT
298     dpy = XOpenDisplay (NULL);
299     if (!dpy)
300     {
301         fprintf (stderr, "failed: open display\n");
302         exit (-1);
303     }
304 #endif
305
306     for (i = 0 ; i < sizeof (Evlog_extensions) / sizeof (ExtensionInfo); i++)
307     {
308         Evlog_extensions[i].get_base_func (dpy, Evlog_extensions + i);
309     }
310
311     if(!_SortEvlogExtensions ())
312         return FALSE;
313
314 #ifdef XDBG_CLIENT
315     XCloseDisplay (dpy);
316 #endif
317
318     *return_extensions_size = sizeof(Evlog_extensions);
319     success = TRUE;
320
321     return success;
322 }
323
324
325 void
326 xDbgEvlogFillLog (EvlogInfo *evinfo, char *reply, int *len)
327 {
328     static CARD32 prev;
329     static int Extensions_size = 0;
330
331     RETURN_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_dir) / sizeof (char*)));
332     RETURN_IF_FAIL (evinfo->type >= 0 && (sizeof (evt_type) / sizeof (char*)));
333
334     REPLY ("[%10.3f][%5ld] %22s(%2d:%5d) %s %s",
335                 evinfo->time / 1000.0,
336                 evinfo->time - prev,
337                 xDbgEvlogGetCmd (evinfo->client.command),
338                 evinfo->client.index,
339                 evinfo->client.pid,
340                 evt_dir[evinfo->type],
341                 evt_type[evinfo->type]);
342
343     if (evinfo->type == REQUEST && _EvlogGetExtentionEntry (&Extensions_size))
344     {
345         REPLY ("(");
346         reply = xDbgEvlogReqeust (evinfo, Extensions_size, reply, len);
347         REPLY (")");
348     }
349     else if (evinfo->type == EVENT && _EvlogGetExtentionEntry (&Extensions_size))
350     {
351         REPLY ("(");
352         reply = xDbgEvlogEvent (evinfo, Extensions_size, reply, len);
353         REPLY (")");
354     }
355     else
356     {
357         const char *evlog_name = "";
358         if (evinfo->type == REQUEST)
359             evlog_name = evinfo->req.name;
360         else if (evinfo->type == EVENT)
361             evlog_name = evinfo->evt.name;
362         REPLY ("(%s)", evlog_name);
363     }
364
365     REPLY ("\n");
366
367     prev = evinfo->time;
368 }
369
370
371