fix: prevent bug
[adaptation/xorg/driver/xserver-xorg-module-xdbg.git] / module / xdbg_module_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 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <sys/types.h>
40 #include <sys/fcntl.h>
41 #include <unistd.h>
42 #include <stdarg.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <time.h>
46
47 #define __USE_GNU
48 #include <sys/socket.h>
49 #include <linux/socket.h>
50
51 #ifdef HAS_GETPEERUCRED
52 # include <ucred.h>
53 #endif
54
55 #include <xace.h>
56 #include <xacestr.h>
57 #include <X11/Xatom.h>
58 #include <X11/extensions/XI2proto.h>
59 #include <windowstr.h>
60
61 #include <xdbg.h>
62
63 #include "xdbg_module_types.h"
64 #include "xdbg_module_evlog.h"
65 #include "xdbg_module_evlog_request.h"
66 #include "xdbg_module_evlog_event.h"
67 #include "bool_exp_rule_checker.h"
68
69 #define XREGISTRY
70 #include "registry.h"
71
72 #define FP1616toDBL(x) ((x) * 1.0 / (1 << 16))
73
74 static Bool     xev_trace_on = FALSE;
75 static int  xev_trace_fd = -1;
76 static int  xev_trace_record_fd = -1;
77 static Atom atom_rotate = None;
78 static Atom atom_client_pid = None;
79
80 RULE_CHECKER rc = NULL;
81
82 #define UNKNOWN_EVENT "<unknown>"
83
84 typedef enum
85 {
86     EVENT,
87     REQUEST,
88     REPLY,
89     FLUSH
90 } evtType;
91
92 #define EVTDATA_MASK_CLIENT_INFO    0x1
93 #define EVTDATA_MASK_CLIENT_REQ     0x2
94 #define EVTDATA_MASK_EVENT          0x4
95
96 static char *evt_type[] = { "Event", "Request", "Reply", "Flush" };
97 static char *evt_dir[]  = { "<====", "---->",   "<----", "*****" };
98
99 static void _evtPrintF (int fd, const char * format, ...)
100 {
101     va_list args;
102
103     va_start (args, format);
104     if (fd < 0)
105         VErrorF (format, args);
106     else
107         vdprintf (fd, format, args);
108     va_end (args);
109 }
110
111 static void evtGetReqInfo (evtType type, EvlogClientInfo *evinfo, xReq *req, xEvent *ev,
112                            int *req_id, const char **req_string,
113                            char **c_cmd, int *c_index, int *c_pid)
114 {
115     if (type == REQUEST && req)
116     {
117         *req_id = req->reqType;
118         if (req->reqType < EXTENSION_BASE)
119             *req_string = LookupRequestName (req->reqType, 0);
120         else
121             *req_string = LookupRequestName (req->reqType, req->data);
122     }
123     else if (type == EVENT && ev)
124         *req_string = LookupEventName ((int)(ev->u.u.type));
125
126     if(evinfo)
127     {
128         *c_index = evinfo->index;
129         *c_pid = evinfo->pid;
130
131         *c_cmd = rindex (evinfo->command, '/');
132         if (*c_cmd == NULL)
133             *c_cmd = evinfo->command;
134         else
135             *c_cmd = *c_cmd + 1;
136     }
137 }
138
139 static void evtRecord (CARD32 msec, evtType type, EvlogClientInfo *evinfo, xEvent *ev)
140 {
141     int mask = 0;
142     int write_len = sizeof (int) +
143                     sizeof (CARD32) +
144                     sizeof (evtType) +
145                     sizeof (int);
146
147     if (xev_trace_record_fd < 0)
148         return;
149
150     if (evinfo)
151     {
152         mask |= EVTDATA_MASK_CLIENT_INFO;
153         write_len += sizeof (EvlogClientInfo);
154
155         if (evinfo->requestBuffer)
156         {
157             mask |= EVTDATA_MASK_CLIENT_REQ;
158             write_len += evinfo->req_len;
159         }
160     }
161
162     if (ev)
163     {
164         mask |= EVTDATA_MASK_EVENT;
165         write_len += sizeof (xEvent);
166     }
167
168     if (write (xev_trace_record_fd, &write_len, sizeof(int)) == -1)
169     {
170         XDBG_ERROR (MXDBG, "failed: write write_len\n");
171         return;
172     }
173     if (write (xev_trace_record_fd, &msec, sizeof(CARD32)) == -1)
174     {
175         XDBG_ERROR (MXDBG, "failed: write msec\n");
176         return;
177     }
178     if (write (xev_trace_record_fd, &type, sizeof(evtType)) == -1)
179     {
180         XDBG_ERROR (MXDBG, "failed: write type\n");
181         return;
182     }
183     if (write (xev_trace_record_fd, &mask, sizeof(int)) == -1)
184     {
185         XDBG_ERROR (MXDBG, "failed: write mask\n");
186         return;
187     }
188
189     if (evinfo)
190     {
191         if (write (xev_trace_record_fd, evinfo, sizeof (EvlogClientInfo)) == -1)
192         {
193             XDBG_ERROR (MXDBG, "failed: write client\n");
194             return;
195         }
196         if (evinfo->requestBuffer)
197             if (write (xev_trace_record_fd, evinfo->requestBuffer, evinfo->req_len) == -1)
198             {
199                 XDBG_ERROR (MXDBG, "failed: write requestBuffer\n");
200                 return;
201             }
202     }
203
204     if (ev)
205         if (write (xev_trace_record_fd, ev, sizeof (xEvent)) == -1)
206         {
207             XDBG_ERROR (MXDBG, "failed: write ev\n");
208             return;
209         }
210 }
211
212 static void evtPrintF (int fd, CARD32 msec, evtType type, EvlogClientInfo *evinfo, xEvent *ev)
213 {
214     int   req_id = 0;
215     const char *req_string = "";
216     const char *req_detail = "";
217     char  tempbuf[256] = {0,};
218     char *c_cmd = "";
219     int   c_index = 0;
220     int   c_pid = 0;
221     static CARD32 prev;
222     xReq *req = NULL;
223
224     XDBG_RETURN_IF_FAIL (type >= 0 && (sizeof (evt_dir) / sizeof (char*)));
225     XDBG_RETURN_IF_FAIL (type >= 0 && (sizeof (evt_type) / sizeof (char*)));
226
227     if(evinfo)
228     {
229         req = (xReq *)evinfo->requestBuffer;
230     }
231
232     evtGetReqInfo (type, evinfo, req, ev, &req_id, &req_string, &c_cmd, &c_index, &c_pid);
233
234     if (type == REQUEST)
235     {
236         XDBG_RETURN_IF_FAIL (evinfo != NULL);
237         XDBG_RETURN_IF_FAIL (req != NULL);
238         xDbgModuleEvlogReqeust (evinfo, req, tempbuf, sizeof (tempbuf));
239         req_detail = tempbuf;
240     }
241     else if (type == EVENT)
242     {
243         XDBG_RETURN_IF_FAIL (ev != NULL);
244         xDbgModuleEvlogEvent (ev, tempbuf, sizeof (tempbuf));
245         req_detail = tempbuf;
246     }
247     else
248         req_detail = req_string;
249
250     _evtPrintF (fd, "[%10.3f][%4ld] %15s(%2d:%4d) %s %7s (%s)\n",
251                 msec / 1000.0,
252                 msec - prev,
253                 c_cmd, c_index, c_pid,
254                 evt_dir[type],
255                 evt_type[type], req_detail);
256
257     prev = msec;
258 }
259
260 static void evtPrint (evtType type, ClientPtr client, xEvent *ev)
261 {
262     int   req_id = 0;
263     const char *req_string = "";
264     char *c_cmd = "";
265     int   c_index = 0;
266     int   c_pid = 0;
267     CARD32 curr;
268     ModuleClientInfo *info = NULL;
269     EvlogClientInfo evinfo;
270     xReq *req = NULL;
271
272     if (xev_trace_on == FALSE)
273         return;
274
275     if (client)
276     {
277         info = GetClientInfo (client);
278         XDBG_RETURN_IF_FAIL (info != NULL);
279
280         memset (&evinfo, 0, sizeof (EvlogClientInfo));
281
282         evinfo.index = info->index;
283         evinfo.pid = info->pid;
284         evinfo.gid = info->gid;
285         evinfo.uid = info->uid;
286         strncpy (evinfo.command, info->command, strlen (info->command));
287         evinfo.requestBuffer = client->requestBuffer;
288         evinfo.req_len = client->req_len;
289
290         req = (xReq *)evinfo.requestBuffer;
291     }
292
293     evtGetReqInfo (type, (client)?&evinfo:NULL, req, ev, &req_id, &req_string, &c_cmd, &c_index, &c_pid);
294
295     if (rc == NULL)
296         rc = rulechecker_init();
297
298     if (!rulechecker_validate_rule (rc, type, req_id, req_string, c_pid, c_cmd))
299         return;
300
301     curr = GetTimeInMillis ();
302
303     if (xev_trace_record_fd >= 0)
304         evtRecord (curr, type, (client)?&evinfo:NULL, ev);
305     else
306         evtPrintF (xev_trace_fd, curr, type, (client)?&evinfo:NULL, ev);
307 }
308
309 static void _mergeArgs (char * target, int argc, const char ** argv)
310 {
311     int i;
312     int len;
313
314     for (i=0; i<argc; i++)
315     {
316         len = sprintf (target, "%s", argv[i]);
317         target += len;
318
319         if (i != argc - 1)
320             *(target++) = ' ';
321     }
322 }
323
324 static const char*
325 _traceGetWindowName (ClientPtr client, Window window)
326 {
327     int rc;
328     WindowPtr pWin;
329     Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
330     Atom property;
331     PropertyPtr pProp;
332     static char winname[128];
333     int datalen;
334
335     rc = dixLookupWindow (&pWin, window, client, win_mode);
336     if (rc != Success)
337         return NULL;
338
339     property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
340     while (pWin)
341     {
342         rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
343         if (rc == Success && pProp->data)
344         {
345             datalen = (pProp->size>127) ?127:pProp->size;
346             strncpy (winname, pProp->data, datalen);
347             winname[datalen] = 0;
348
349             return winname;
350         }
351
352         pWin = pWin->parent;
353     }
354
355     return NULL;
356 }
357
358 static void
359 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
360 {
361     evtPrint (FLUSH, NULL, NULL);
362 }
363
364 static void
365 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
366 {
367     ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
368
369     evtPrint (REPLY, pri->client, NULL);
370 }
371
372 static void
373 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
374 {
375     EventInfoRec *pei = (EventInfoRec*)calldata;
376     ClientPtr pClient;
377     ModuleClientInfo *info;
378     int ev; /* event index */
379     static int xi2_opcode = -1;
380     xEvent *pev;
381     static char* ename[]=
382     {
383         "KeyPress",
384         "KeyRelease",
385         "ButtonPress",
386         "ButtonRelease",
387     };
388
389     XDBG_RETURN_IF_FAIL (pei != NULL);
390
391     pClient = pei->client;
392     XDBG_RETURN_IF_FAIL (pClient != NULL);
393
394     pev = pei->events;
395     XDBG_RETURN_IF_FAIL (pev != NULL);
396
397     info = GetClientInfo (pClient);
398     XDBG_RETURN_IF_FAIL (info != NULL);
399
400     for (ev=0; ev < pei->count; ev++, pev++)
401     {
402         int type = pev->u.u.type & 0177;
403
404         if (type < LASTEvent)
405         {
406             switch (type)
407             {
408             case KeyPress:
409             case KeyRelease:
410                 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
411                         , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
412                         , info->command, info->pid
413                         , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
414                         , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
415                         , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
416                 break;
417
418             case ButtonPress:
419             case ButtonRelease:
420                 XDBG_INFO (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%lx) root(%d,%d) win(%d,%d)\n"
421                         , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
422                         , info->command, info->pid
423                         , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), pev->u.keyButtonPointer.event
424                         , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
425                         , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
426                 break;
427             case GenericEvent:
428                 if(!xi2_opcode) break;
429                 if(xi2_opcode < 0)
430                 {
431                     ExtensionEntry *pExt = CheckExtension("XInputExtension");
432                     if(!pExt) xi2_opcode = 0;
433                     else xi2_opcode = pExt->base;
434                 }
435
436                 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
437
438                 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
439                 if(xidev->deviceid==2) break;
440                 if(xidev->evtype==XI_ButtonPress)
441                     XDBG_TRACE (MXDBG, "XI_ButtonPress(%d) device(%d), event win(0x%x), child(0x%x), root(%.f,%.f), win(%.f, %.f)\n", XI_ButtonPress, xidev->deviceid, xidev->event, xidev->child, FP1616toDBL(xidev->root_x), FP1616toDBL(xidev->root_y), FP1616toDBL(xidev->event_x), FP1616toDBL(xidev->event_y));
442                 else if(xidev->evtype==XI_ButtonRelease)
443                     XDBG_TRACE (MXDBG, "XI_ButtonRelease(%d) device(%d), event win(0x%x), child(0x%x), root(%.f,%.f), win(%.f, %.f)\n", XI_ButtonRelease,  xidev->deviceid, xidev->event, xidev->child, FP1616toDBL(xidev->root_x), FP1616toDBL(xidev->root_y), FP1616toDBL(xidev->event_x), FP1616toDBL(xidev->event_y));
444                 else if(xidev->evtype==XI_Motion)
445                     XDBG_TRACE (MXDBG, "XI_Motion(%d) device(%d), event win(0x%x), child(0x%x), root(%.f,%.f), win(%.f, %.f)\n", XI_Motion, xidev->deviceid, xidev->event, xidev->child, FP1616toDBL(xidev->root_x), FP1616toDBL(xidev->root_y), FP1616toDBL(xidev->event_x), FP1616toDBL(xidev->event_y));
446                 break;
447             default:
448                 break;
449             }
450         }
451
452         evtPrint (EVENT, pClient, pev);
453     }
454 }
455
456 static void
457 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
458 {
459     XaceCoreDispatchRec *rec = calldata;
460
461     XDBG_RETURN_IF_FAIL (rec != NULL);
462
463     evtPrint (REQUEST, rec->client, NULL);
464 }
465
466 static void
467 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
468 {
469     XaceExtAccessRec *rec = calldata;
470
471     XDBG_RETURN_IF_FAIL (rec != NULL);
472
473     evtPrint (REQUEST, rec->client, NULL);
474 }
475
476 static void
477 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
478 {
479     XacePropertyAccessRec *rec = calldata;
480     ModuleClientInfo *info = GetClientInfo (rec->client);
481     PropertyPtr pProp = *rec->ppProp;
482     Atom name = pProp->propertyName;
483
484     /* Don't care about the new content check */
485     if (rec->client == serverClient || rec->access_mode & DixPostAccess)
486         return;
487
488     if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
489     {
490         XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
491         rec->status = BadAccess;
492         return;
493     }
494
495     rec->status = Success;
496     return;
497 }
498
499 static void
500 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
501 {
502     XaceResourceAccessRec *rec = calldata;
503     Mask access_mode = rec->access_mode;
504     ModuleClientInfo *info = GetClientInfo (rec->client);
505
506     /* Perform the background none check on windows */
507     if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
508     {
509         WindowPtr pWin = (WindowPtr) rec->res;
510         int rc;
511         int pid = info->pid;
512
513         rc = dixChangeWindowProperty (serverClient,
514                                       pWin, atom_client_pid, XA_CARDINAL, 32,
515                                       PropModeReplace, 1, &pid, FALSE);
516         if (rc != Success)
517             XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
518     }
519 }
520
521 static void
522 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
523 {
524     XaceReceiveAccessRec *rec = calldata;
525
526     if (rec->events->u.u.type != VisibilityNotify)
527         return;
528
529     rec->status = BadAccess;
530 }
531
532 Bool
533 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
534 {
535     int ret = TRUE;
536
537     ret &= AddCallback (&EventCallback, _traceEvent, NULL);
538     ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
539     ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
540     ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
541     ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
542
543     /*Disable Visibility Event*/
544     ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
545
546     if (atom_client_pid == None)
547         atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
548     if (atom_rotate == None)
549         atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
550
551     if (!ret)
552     {
553         XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
554         return FALSE;
555     }
556
557     if (pMod && pMod->evlog_path)
558         xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
559
560     return TRUE;
561 }
562
563 void
564 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
565 {
566     DeleteCallback (&EventCallback, _traceEvent, NULL);
567     DeleteCallback (&FlushCallback, _traceFlush, NULL);
568     DeleteCallback (&ReplyCallback, _traceAReply, NULL);
569     XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
570     XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
571 }
572
573 void
574 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
575 {
576     int ret = TRUE;
577
578     xev_trace_on = on;
579
580     if (xev_trace_on)
581     {
582         int i;
583
584         //Find client's pid
585         for (i=1 ; i< currentMaxClients ; i++)
586         {
587             ClientPtr pClient;
588             ModuleClientInfo *info;
589
590             pClient = clients[i];
591             if (!pClient)
592                 continue;
593
594             info = GetClientInfo (pClient);
595             if (!info)
596                 continue;
597
598             if (strlen (info->command) > 0 && strstr (client_name, info->command))
599             {
600                 char fd_name[256];
601
602                 if (xev_trace_fd >= 0)
603                     close (xev_trace_fd);
604
605                 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
606                 xev_trace_fd = open (fd_name, O_RDWR);
607                 if (xev_trace_fd < 0)
608                     XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
609             }
610         }
611
612
613         ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
614         ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
615
616         if (!ret)
617         {
618             XDBG_REPLY ("failed: register one or more callbacks.\n");
619             return;
620         }
621     }
622     else
623     {
624         XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
625         XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
626     }
627
628     return;
629 }
630
631 int
632 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
633 {
634     const char * command;
635
636     if (rc == NULL)
637         rc = rulechecker_init();
638
639     if (argc == 0)
640     {
641         rulechecker_print_rule (rc, reply);
642         return 0;
643     }
644
645     command = argv[0];
646
647     if (!strcasecmp (command, "add"))
648     {
649         POLICY_TYPE policy_type;
650         RC_RESULT_TYPE result;
651         const char * policy = argv[1];
652         char rule[8192];
653
654         if (argc < 3)
655         {
656             XDBG_REPLY ("Error : Too few arguments.\n");
657             return -1;
658         }
659
660         if (!strcasecmp (policy, "ALLOW"))
661             policy_type = ALLOW;
662         else if (!strcasecmp (policy, "DENY"))
663             policy_type = DENY;
664         else
665         {
666             XDBG_REPLY ("Error : Unknown policy : [%s].\n          Policy should be ALLOW or DENY.\n", policy);
667             return -1;
668         }
669
670         _mergeArgs (rule, argc - 2, &(argv[2]));
671
672         result = rulechecker_add_rule (rc, policy_type, rule);
673         if (result == RC_ERR_TOO_MANY_RULES)
674         {
675             XDBG_REPLY ("Error : Too many rules were added.\n");
676             return -1;
677         }
678         else if (result == RC_ERR_PARSE_ERROR)
679         {
680             XDBG_REPLY ("Error : An error occured during parsing the rule [%s]\n", rule);
681             return -1;
682         }
683
684         XDBG_REPLY ("The rule was successfully added.\n\n");
685         rulechecker_print_rule (rc, reply);
686         return 0;
687     }
688     else if (!strcasecmp (command, "remove"))
689     {
690         const char * remove_idx;
691         int i;
692
693         if (argc < 2)
694         {
695             XDBG_REPLY ("Error : Too few arguments.\n");
696             return -1;
697         }
698
699         for (i=0; i<argc - 1; i++)
700         {
701             remove_idx = argv[i+1];
702
703             if (!strcasecmp (remove_idx, "all"))
704             {
705                 rulechecker_destroy (rc);
706                 rc = rulechecker_init();
707                 XDBG_REPLY ("Every rules were successfully removed.\n");
708             }
709             else
710             {
711                 int index = atoi (remove_idx);
712                 if (isdigit (*remove_idx) && rulechecker_remove_rule (rc, index) == 0)
713                     XDBG_REPLY ("The rule [%d] was successfully removed.\n", index);
714                 else
715                     XDBG_REPLY ("Rule remove fail : No such rule [%s].\n", remove_idx);
716             }
717         }
718         rulechecker_print_rule (rc, reply);
719         return 0;
720     }
721     else if (!strcasecmp (command, "print"))
722     {
723         rulechecker_print_rule (rc, reply);
724         return 0;
725     }
726     else if (!strcasecmp (command, "help"))
727     {
728         XDBG_REPLY ("%s", rulechecker_print_usage());
729         return 0;
730     }
731
732     XDBG_REPLY ("%s\nUnknown command : [%s].\n\n", rulechecker_print_usage(), command);
733
734     return 0;
735 }
736
737 Bool
738 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
739 {
740     char fd_name[XDBG_PATH_MAX];
741     char *temp[3] = {"/", "./", "../"};
742     Bool valid = FALSE;
743     int i;
744
745     if (!path || strlen (path) <= 0)
746     {
747         XDBG_REPLY ("failed: invalid path\n");
748         return FALSE;
749     }
750
751     if (xev_trace_record_fd >= 0)
752     {
753         close (xev_trace_record_fd);
754         xev_trace_record_fd = -1;
755     }
756
757     if (!strcmp (path, "console"))
758     {
759         if (pid > 0)
760         {
761             char fd_name[256];
762
763             if (xev_trace_fd >= 0)
764                 close (xev_trace_fd);
765
766             snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
767
768             xev_trace_fd = open (fd_name, O_RDWR);
769             if (xev_trace_fd < 0)
770                 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
771         }
772
773         return TRUE;
774     }
775
776     for (i = 0; i < sizeof (temp) / sizeof (char*); i++)
777         if (path == strstr (path, temp[i]))
778         {
779             valid = TRUE;
780             break;
781         }
782
783     if (!valid)
784     {
785         XDBG_REPLY ("failed: invalid path(%s)\n", path);
786         return FALSE;
787     }
788
789     if (path[0] == '/')
790         snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
791     else
792     {
793         char cwd[128];
794         if (getcwd (cwd, sizeof (cwd)))
795             snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", cwd, path);
796         else
797             snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
798     }
799
800     xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
801     if (xev_trace_record_fd < 0)
802     {
803         XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));
804         return FALSE;
805     }
806
807     return TRUE;
808 }
809
810 void
811 xDbgModuleEvlogPrintEvlog (XDbgModule *pMod, int pid, char *evlog_path, char *reply, int *len)
812 {
813     int fd = -1, cfd = -1;
814     int total, read_len;
815     int evlog_len;
816     pointer requestBuffer = NULL;
817     char fd_name[256];
818
819     if (!evlog_path)
820     {
821         XDBG_REPLY ("failed: no evlog path\n");
822         return;
823     }
824
825     fd = open (evlog_path, O_RDONLY);
826     if (fd < 0)
827     {
828         XDBG_REPLY ("failed: open '%s'. (%s)\n", evlog_path, strerror(errno));
829         return;
830     }
831
832     snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
833     cfd = open (fd_name, O_RDWR);
834     if (cfd < 0)
835     {
836         XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
837         goto print_done;
838     }
839
840     while ((read_len = read (fd, &evlog_len, sizeof (int))) == sizeof (int))
841     {
842         CARD32 msec;
843         evtType type;
844         int mask;
845         EvlogClientInfo evinfo;
846         xEvent ev;
847
848         total = read_len;
849
850         read_len = read (fd, &msec, sizeof (CARD32));
851         XDBG_GOTO_IF_FAIL (read_len == sizeof (CARD32), print_done);
852         total += read_len;
853
854         read_len = read (fd, &type, sizeof (evtType));
855         XDBG_GOTO_IF_FAIL (read_len == sizeof (evtType), print_done);
856         XDBG_GOTO_IF_FAIL (type >= EVENT && type <= FLUSH, print_done);
857         total += read_len;
858
859         read_len = read (fd, &mask, sizeof (int));
860         XDBG_GOTO_IF_FAIL (read_len == sizeof (int), print_done);
861         total += read_len;
862
863         if (mask & EVTDATA_MASK_CLIENT_INFO)
864         {
865             read_len = read (fd, &evinfo, sizeof (EvlogClientInfo));
866             XDBG_GOTO_IF_FAIL (read_len == sizeof (EvlogClientInfo), print_done);
867             total += read_len;
868
869             if ((mask & EVTDATA_MASK_CLIENT_REQ) && (evinfo.req_len > 0))
870             {
871                 requestBuffer = malloc (evinfo.req_len);
872                 XDBG_GOTO_IF_FAIL (requestBuffer != NULL, print_done);
873
874                 read_len = read (fd, requestBuffer, evinfo.req_len);
875                 XDBG_GOTO_IF_FAIL (read_len == evinfo.req_len, print_done);
876                 total += read_len;
877
878                 evinfo.requestBuffer = requestBuffer;
879             }
880         }
881
882         if (mask & EVTDATA_MASK_EVENT)
883         {
884             read_len = read (fd, &ev, sizeof (xEvent));
885             XDBG_GOTO_IF_FAIL (read_len == sizeof (xEvent), print_done);
886             total += read_len;
887         }
888
889         XDBG_GOTO_IF_FAIL (evlog_len == total, print_done);
890
891         evtPrintF (cfd, msec, type, &evinfo, &ev);
892
893         if (requestBuffer)
894         {
895             free (requestBuffer);
896             requestBuffer = NULL;
897         }
898     }
899
900 print_done:
901     if (requestBuffer)
902         free (requestBuffer);
903
904     if (cfd >= 0)
905         close (cfd);
906
907     if (fd >= 0)
908         close (fd);
909 }