tizen 2.4 release
[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 #include "xdbg_types.h"
63 #include "xdbg_module.h"
64 #include "xdbg_module_evlog.h"
65 #include "xdbg_evlog.h"
66
67 #define XREGISTRY
68 #include "registry.h"
69
70 #include <dlog.h>
71
72 #define FP1616toDBL(x) ((x) * 1.0 / (1 << 16))
73
74 Bool        xev_trace_on = FALSE;
75 int         xev_trace_detail_level = EVLOG_PRINT_DEFAULT;
76 static int  xev_trace_fd = -1;
77 static int  xev_trace_record_fd = -1;
78 static Atom atom_client_pid = None;
79 static int  init = 0;
80 static char *xerror_path = NULL;
81
82 void
83 xDbgModuleEvlogXErrorSetPath (char *path)
84 {
85     xerror_path = path;
86 }
87
88 static void xErrorPrint (EvlogInfo *evinfo, const char *f, ...)
89 {
90     va_list args;
91
92     va_start (args, f);
93     if (!strcmp (xerror_path, "dlog"))
94     {
95         const char * error_tag = "XERROR";
96         SLOG_VA (LOG_DEBUG, error_tag, f, args);
97     }
98     else if (!strcmp (xerror_path, "xorg"))
99     {
100         LogVWrite (1, f, args);
101     }
102     va_end (args);
103 }
104
105 static void evtRecord (int fd, EvlogInfo *evinfo)
106 {
107     extern ExtensionInfo Evlog_extensions[];
108     extern int Extensions_size;
109     int write_len = 0;
110     int i;
111
112     XDBG_RETURN_IF_FAIL (fd >= 0)
113     XDBG_RETURN_IF_FAIL (evinfo != NULL);
114
115     write_len = sizeof (int) +
116                 sizeof (EvlogType) +
117                 sizeof (int) +
118                 sizeof (CARD32);
119
120     if (evinfo->mask & EVLOG_MASK_CLIENT)
121         write_len += sizeof (EvlogClient);
122
123     if (evinfo->mask & EVLOG_MASK_REQUEST)
124         write_len += (sizeof (EvlogRequest) + (evinfo->req.length * 4));
125
126     if (evinfo->mask & EVLOG_MASK_EVENT)
127         write_len += (sizeof (EvlogEvent) + evinfo->evt.size);
128
129     if (evinfo->mask & EVLOG_MASK_REPLY)
130         write_len += (sizeof (EvlogReply) + evinfo->rep.size);
131
132     if (evinfo->mask & EVLOG_MASK_ERROR)
133         write_len += (sizeof (EvlogError));
134
135     if (evinfo->mask & EVLOG_MASK_ATOM)
136         write_len += (sizeof (int) +
137                      (sizeof (EvlogAtomTable) * evinfo->evatom.size));
138
139     if (evinfo->mask & EVLOG_MASK_REGION)
140         write_len += (sizeof (int) +
141                      (sizeof (EvlogRegionTable) * evinfo->evregion.size));
142
143     if (!init)
144         write_len += (sizeof (int) +
145                     ((sizeof (int) * 3) * Extensions_size));
146
147     if (write (fd, &write_len, sizeof(int)) == -1)
148     {
149         XDBG_ERROR (MXDBG, "failed: write write_len\n");
150         return;
151     }
152
153     if (!init)
154     {
155         if (write (fd, &Extensions_size, sizeof(int)) == -1)
156         {
157             XDBG_ERROR (MXDBG, "failed: write Extensions_size\n");
158             return;
159         }
160
161         for (i = 0 ; i < Extensions_size ; i++)
162         {
163             if (write (fd, &Evlog_extensions[i].opcode, sizeof(int)) == -1)
164             {
165                 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] opcode\n", i);
166                 return;
167             }
168             if (write (fd, &Evlog_extensions[i].evt_base, sizeof(int)) == -1)
169             {
170                 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] evt_base\n", i);
171                 return;
172             }
173             if (write (fd, &Evlog_extensions[i].err_base, sizeof(int)) == -1)
174             {
175                 XDBG_ERROR (MXDBG, "failed: write Evlog_extensions[%d] err_base\n", i);
176                 return;
177             }
178         }
179
180         init = 1;
181     }
182
183     if (write (fd, &evinfo->time, sizeof(CARD32)) == -1)
184     {
185         XDBG_ERROR (MXDBG, "failed: write msec\n");
186         return;
187     }
188     if (write (fd, &evinfo->type, sizeof(EvlogType)) == -1)
189     {
190         XDBG_ERROR (MXDBG, "failed: write type\n");
191         return;
192     }
193     if (write (fd, &evinfo->mask, sizeof(int)) == -1)
194     {
195         XDBG_ERROR (MXDBG, "failed: write mask\n");
196         return;
197     }
198
199     if (evinfo->mask & EVLOG_MASK_CLIENT)
200         if (write (fd, &evinfo->client, sizeof (EvlogClient)) == -1)
201         {
202             XDBG_ERROR (MXDBG, "failed: write client\n");
203             return;
204         }
205
206     if (evinfo->mask & EVLOG_MASK_REQUEST)
207     {
208         if (write (fd, &evinfo->req, sizeof (EvlogRequest)) == -1)
209         {
210             XDBG_ERROR (MXDBG, "failed: write request\n");
211             return;
212         }
213         if (write (fd, evinfo->req.ptr, (evinfo->req.length * 4)) == -1)
214         {
215             XDBG_ERROR (MXDBG, "failed: write request\n");
216             return;
217         }
218     }
219     if (evinfo->mask & EVLOG_MASK_EVENT)
220     {
221         if (write (fd, &evinfo->evt, sizeof (EvlogEvent)) == -1)
222         {
223             XDBG_ERROR (MXDBG, "failed: write event\n");
224             return;
225         }
226
227         XDBG_WARNING_IF_FAIL (evinfo->evt.size > 0);
228         if (write (fd, evinfo->evt.ptr, evinfo->evt.size) == -1)
229         {
230             XDBG_ERROR (MXDBG, "failed: write event\n");
231             return;
232         }
233     }
234     if (evinfo->mask & EVLOG_MASK_REPLY)
235     {
236         if (write (fd, &evinfo->rep, sizeof (EvlogReply)) == -1)
237         {
238             XDBG_ERROR (MXDBG, "failed: write reply\n");
239             return;
240         }
241
242         XDBG_WARNING_IF_FAIL (evinfo->rep.size > 0);
243         if (write (fd, evinfo->rep.ptr, evinfo->rep.size) == -1)
244         {
245             XDBG_ERROR (MXDBG, "failed: write reply\n");
246             return;
247         }
248     }
249     if (evinfo->mask & EVLOG_MASK_ERROR)
250     {
251         if (write (fd, &evinfo->err, sizeof (EvlogError)) == -1)
252         {
253             XDBG_ERROR (MXDBG, "failed: write reply\n");
254             return;
255         }
256     }
257
258     if (evinfo->mask & EVLOG_MASK_ATOM)
259     {
260         EvlogAtomTable *table = NULL;
261
262         if (write (fd, &evinfo->evatom.size, sizeof (int)) == -1)
263         {
264             XDBG_ERROR (MXDBG, "failed: write atom size\n");
265             return;
266         }
267         xorg_list_for_each_entry(table, &evinfo->evatom.list, link)
268             if (write (fd, table, sizeof (EvlogAtomTable)) == -1)
269             {
270                 XDBG_ERROR (MXDBG, "failed: write atom table\n");
271                 return;
272             }
273     }
274
275     if (evinfo->mask & EVLOG_MASK_REGION)
276     {
277         EvlogRegionTable *table = NULL;
278
279         if (write (fd, &evinfo->evregion.size, sizeof (int)) == -1)
280         {
281             XDBG_ERROR (MXDBG, "failed: write region size\n");
282             return;
283         }
284         xorg_list_for_each_entry(table, &evinfo->evregion.list, link)
285             if (write (fd, table, sizeof (EvlogRegionTable)) == -1)
286             {
287                 XDBG_ERROR (MXDBG, "failed: write region table\n");
288                 return;
289             }
290     }
291 }
292
293 static void evtPrintF (int fd, EvlogInfo *evinfo, char *log)
294 {
295     if (fd < 0)
296         ErrorF ("%s", log);
297     else
298         dprintf (fd, "%s", log);
299 }
300
301 static void evtPrint (EvlogType type, ClientPtr client, xEvent *ev, ReplyInfoRec *rep)
302 {
303     EvlogInfo evinfo = {0,};
304     static int EntryInit = 0;
305
306     /* evinfo.type */
307     evinfo.type = type;
308
309     /* evinfo.client */
310     if (client)
311     {
312         ModuleClientInfo *info = GetClientInfo (client);
313         XDBG_RETURN_IF_FAIL (info != NULL);
314         int min;
315
316         evinfo.mask |= EVLOG_MASK_CLIENT;
317         evinfo.client.index = info->index;
318         evinfo.client.pid = info->pid;
319         evinfo.client.gid = info->gid;
320         evinfo.client.uid = info->uid;
321
322         min = MIN (sizeof (evinfo.client.command) - 1, strlen (info->command));
323         strncpy (evinfo.client.command, info->command, min);
324         evinfo.client.command[min] = '\0';
325
326         evinfo.client.pClient = (void*)client;
327
328         /* evinfo.req */
329         if (type == REQUEST)
330         {
331             extern char *conn[];
332
333             REQUEST (xReq);
334
335             evinfo.mask |= EVLOG_MASK_REQUEST;
336             evinfo.req.id = stuff->reqType;
337             evinfo.req.length = client->req_len;
338             evinfo.req.ptr = client->requestBuffer;
339
340             if (client->requestVector == InitialVector && stuff->reqType == 1)
341                 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[0]);
342             else if (client->requestVector == InitialVector  && stuff->reqType == 2)
343                 snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s", conn[1]);
344             else
345             {
346                 if (stuff->reqType < EXTENSION_BASE)
347                     snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
348                               LookupRequestName (stuff->reqType, 0));
349                 else
350                     snprintf (evinfo.req.name, sizeof (evinfo.req.name), "%s",
351                               LookupRequestName (stuff->reqType, stuff->data));
352             }
353         }
354
355         /* evinfo.rep */
356         if (type == REPLY)
357         {
358             REQUEST (xReq);
359
360             evinfo.mask |= EVLOG_MASK_REPLY;
361             evinfo.rep.reqType = stuff->reqType;
362             evinfo.rep.reqData = stuff->data;
363             evinfo.rep.ptr = (xGenericReply*)rep->replyData;
364             evinfo.rep.size = rep->dataLenBytes - rep->padBytes;
365             evinfo.rep.isStart = rep->startOfReply;
366
367             if (stuff->reqType < EXTENSION_BASE)
368                 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
369                           LookupRequestName (stuff->reqType, 0));
370             else
371                 snprintf (evinfo.rep.name, sizeof (evinfo.rep.name), "%s",
372                           LookupRequestName (stuff->reqType, stuff->data));
373         }
374
375         if (type == ERROR || type == XERROR)
376         {
377             xError* err = NULL;
378
379             if (ev)
380                 err = (xError *) ev;
381             else if (rep)
382                 err = (xError *) rep->replyData;
383
384             if (err)
385             {
386                 evinfo.mask |= EVLOG_MASK_ERROR;
387                 evinfo.err.errorCode = err->errorCode;
388                 evinfo.err.resourceID = err->resourceID;
389                 evinfo.err.minorCode = err->minorCode;
390                 evinfo.err.majorCode = err->majorCode;
391                 snprintf (evinfo.err.errorName, sizeof (evinfo.err.errorName), "%s",
392                             LookupErrorName(err->errorCode));
393                 snprintf (evinfo.err.majorName, sizeof (evinfo.err.majorName), "%s",
394                             LookupMajorName(err->majorCode));
395             }
396             else
397                 XDBG_NEVER_GET_HERE (MXDBG);
398         }
399     }
400
401     /* evinfo.evt */
402     if (ev)
403     {
404         if (type == EVENT)
405         {
406             evinfo.mask |= EVLOG_MASK_EVENT;
407             evinfo.evt.ptr = ev;
408             snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
409                       LookupEventName ((int)(ev->u.u.type)));
410         }
411     }
412
413     /* evinfo.time */
414     evinfo.time = GetTimeInMillis ();
415
416     /* get extension entry */
417     if (!EntryInit && !xDbgEvlogGetExtensionEntry ())
418         return;
419
420     EntryInit = 1;
421
422     if (!xDbgEvlogRuleValidate (&evinfo))
423         return;
424
425     if (type == XERROR)
426     {
427         char log[1024];
428         int size = sizeof (log);
429
430         if (xDbgEvlogFillLog (&evinfo, xev_trace_detail_level, log, &size))
431             xErrorPrint (&evinfo, "%s", log);
432     }
433     else if (xev_trace_record_fd >= 0)
434     {
435         if (xDbgEvlogFillLog (&evinfo, EVLOG_PRINT_REPLY_DETAIL, NULL, NULL))
436             evtRecord (xev_trace_record_fd, &evinfo);
437     }
438     else
439     {
440         char log[1024];
441         int size = sizeof (log);
442
443         if (xDbgEvlogFillLog (&evinfo, xev_trace_detail_level, log, &size))
444             evtPrintF (xev_trace_fd, &evinfo, log);
445     }
446
447     /* evatom initialize */
448     xDbgDistroyAtomList(&evinfo);
449     xDbgDistroyRegionList(&evinfo);
450 }
451
452 #if (TIZEN_ENGINEER_MODE || USE_NORMAL_LOG)
453 static const char*
454 _traceGetWindowName (ClientPtr client, Window window)
455 {
456     int rc;
457     WindowPtr pWin;
458     Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
459     Atom property;
460     PropertyPtr pProp;
461     static char winname[128];
462     int datalen;
463
464     rc = dixLookupWindow (&pWin, window, client, win_mode);
465     if (rc != Success)
466         return NULL;
467
468     property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
469     while (pWin)
470     {
471         rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
472         if (rc == Success && pProp->data)
473         {
474             datalen = (pProp->size>127) ?127:pProp->size;
475             strncpy (winname, pProp->data, datalen);
476             winname[datalen] = 0;
477
478             return winname;
479         }
480
481         pWin = pWin->parent;
482     }
483
484     return NULL;
485 }
486 #endif
487
488 static void
489 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
490 {
491     if (xev_trace_on == FALSE)
492         return;
493
494     evtPrint (FLUSH, NULL, NULL, NULL);
495 }
496
497 static void
498 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
499 {
500     if (xev_trace_on == FALSE)
501         return;
502
503     ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
504
505     evtPrint (REPLY, pri->client, NULL, pri);
506 }
507
508 static void
509 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
510 {
511     EventInfoRec *pei = (EventInfoRec*)calldata;
512     ClientPtr pClient;
513     ModuleClientInfo *info;
514     int ev; /* event index */
515     static int xi2_opcode = -1;
516     xEvent *pev;
517
518 #if (TIZEN_ENGINEER_MODE || USE_NORMAL_LOG)
519     static char* ename[]=
520     {
521         "KeyPress",
522         "KeyRelease",
523         "ButtonPress",
524         "ButtonRelease",
525     };
526 #endif
527
528     XDBG_RETURN_IF_FAIL (pei != NULL);
529
530     pClient = pei->client;
531     XDBG_RETURN_IF_FAIL (pClient != NULL);
532
533     pev = pei->events;
534     XDBG_RETURN_IF_FAIL (pev != NULL);
535
536     info = GetClientInfo (pClient);
537     XDBG_RETURN_IF_FAIL (info != NULL);
538
539     for (ev=0; ev < pei->count; ev++, pev++)
540     {
541         int type = pev->u.u.type & 0177;
542
543         if (type < LASTEvent)
544         {
545             switch (type)
546             {
547             case KeyPress:
548             case KeyRelease:
549                 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%x) root(%d,%d) win(%d,%d)\n"
550                         , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
551                         , info->command, info->pid
552                         , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), (unsigned int)pev->u.keyButtonPointer.event
553                         , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
554                         , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
555                 break;
556
557             case ButtonPress:
558             case ButtonRelease:
559                 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%x) root(%d,%d) win(%d,%d)\n"
560                         , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
561                         , info->command, info->pid
562                         , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), (unsigned int)pev->u.keyButtonPointer.event
563                         , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
564                         , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
565                 break;
566             case GenericEvent:
567                 if(!xi2_opcode) break;
568                 if(xi2_opcode < 0)
569                 {
570                     ExtensionEntry *pExt = CheckExtension("XInputExtension");
571                     if(!pExt) xi2_opcode = 0;
572                     else xi2_opcode = pExt->base;
573                 }
574
575                 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
576
577                 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
578                 if(xidev->deviceid==2) break;
579                 if(xidev->evtype==XI_ButtonPress)
580                     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));
581                 else if(xidev->evtype==XI_ButtonRelease)
582                     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));
583                 else if(xidev->evtype==XI_Motion)
584                     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));
585                 break;
586             default:
587                 break;
588             }
589         }
590
591         if (type == X_Error && xerror_path)
592             evtPrint (XERROR, pClient, pev, NULL);
593
594         if (type != X_Error && xev_trace_on)
595             evtPrint (EVENT, pClient, pev, NULL);
596         else if (type == X_Error && xev_trace_on)
597             evtPrint (ERROR, pClient, pev, NULL);
598
599     }
600 }
601
602 static void
603 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
604 {
605     if (xev_trace_on == FALSE)
606         return;
607
608     XaceCoreDispatchRec *rec = calldata;
609
610     XDBG_RETURN_IF_FAIL (rec != NULL);
611
612     evtPrint (REQUEST, rec->client, NULL, NULL);
613 }
614
615 static void
616 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
617 {
618     if (xev_trace_on == FALSE)
619         return;
620
621     XaceExtAccessRec *rec = calldata;
622
623     XDBG_RETURN_IF_FAIL (rec != NULL);
624
625     evtPrint (REQUEST, rec->client, NULL, NULL);
626 }
627
628 static void
629 _traceAuditEndEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
630 {
631     return;
632 }
633
634 static void
635 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
636 {
637     XacePropertyAccessRec *rec = calldata;
638     ModuleClientInfo *info = GetClientInfo (rec->client);
639     PropertyPtr pProp = *rec->ppProp;
640     Atom name = pProp->propertyName;
641
642     /* Don't care about the new content check */
643     if (rec->client == serverClient || rec->access_mode & DixPostAccess)
644         return;
645
646     if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
647     {
648         XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
649         rec->status = BadAccess;
650         return;
651     }
652
653     rec->status = Success;
654     return;
655 }
656
657 static void
658 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
659 {
660     XaceResourceAccessRec *rec = calldata;
661     Mask access_mode = rec->access_mode;
662     ModuleClientInfo *info = GetClientInfo (rec->client);
663
664     /* Perform the background none check on windows */
665     if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
666     {
667         WindowPtr pWin = (WindowPtr) rec->res;
668         int rc;
669         int pid = info->pid;
670
671         rc = dixChangeWindowProperty (serverClient,
672                                       pWin, atom_client_pid, XA_CARDINAL, 32,
673                                       PropModeReplace, 1, &pid, FALSE);
674         if (rc != Success)
675             XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
676     }
677 }
678
679 static void
680 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
681 {
682     XaceReceiveAccessRec *rec = calldata;
683
684     if (rec->events->u.u.type != VisibilityNotify)
685         return;
686
687     rec->status = BadAccess;
688 }
689
690 Bool
691 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
692 {
693     int ret = TRUE;
694
695     ret &= AddCallback (&EventCallback, _traceEvent, NULL);
696     ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
697     ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
698
699     /*Disable Visibility Event*/
700     ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
701
702     if (atom_client_pid == None)
703         atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
704
705     if (!ret)
706     {
707         XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
708         return FALSE;
709     }
710
711     return TRUE;
712 }
713
714 void
715 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
716 {
717     DeleteCallback (&EventCallback, _traceEvent, NULL);
718     XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
719     XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
720 }
721
722 void
723 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
724 {
725     int ret = TRUE;
726
727     on = (on)?TRUE:FALSE;
728     if (xev_trace_on == on)
729         return;
730
731     xev_trace_on = on;
732
733     if (xev_trace_on)
734     {
735         int i;
736
737         //Find client's pid
738         for (i=1 ; i< currentMaxClients ; i++)
739         {
740             ClientPtr pClient;
741             ModuleClientInfo *info;
742
743             pClient = clients[i];
744             if (!pClient)
745                 continue;
746
747             info = GetClientInfo (pClient);
748             if (!info)
749                 continue;
750
751             if (strlen (info->command) > 0 && strstr (client_name, info->command))
752             {
753                 char fd_name[256];
754
755                 if (xev_trace_fd >= 0)
756                     close (xev_trace_fd);
757
758                 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
759                 xev_trace_fd = open (fd_name, O_RDWR);
760                 if (xev_trace_fd < 0)
761                 {
762                     char err_buf[256] = {0,};
763                     char *errp;
764
765                     errp = (char *)strerror_r (errno, err_buf, sizeof(err_buf));
766                     XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, errp);
767                 }
768             }
769         }
770
771         ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
772         ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
773         ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
774         ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
775         ret &= XaceRegisterCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
776
777         if (!ret)
778         {
779             XDBG_REPLY ("failed: register one or more callbacks.\n");
780             return;
781         }
782     }
783     else
784     {
785         DeleteCallback (&FlushCallback, _traceFlush, NULL);
786         DeleteCallback (&ReplyCallback, _traceAReply, NULL);
787         XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
788         XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
789         XaceDeleteCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
790     }
791
792     return;
793 }
794
795 void
796 xDbgModuleEvlogDetail (XDbgModule *pMod, int level, char *reply, int *len)
797 {
798     xev_trace_detail_level = level;
799 }
800
801 int
802 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
803 {
804     return xDbgEvlogRuleSet (argc, argv, reply, len);
805 }
806
807 Bool
808 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
809 {
810     char fd_name[XDBG_PATH_MAX];
811     int  fd_check = -1;
812
813     if (!path || strlen (path) <= 0)
814         return FALSE;
815
816     if (xev_trace_record_fd >= 0)
817     {
818         close (xev_trace_record_fd);
819         xev_trace_record_fd = -1;
820     }
821
822     if (pMod->log_path)
823     {
824         free (pMod->log_path);
825         pMod->log_path = NULL;
826     }
827
828     if (!strcmp (path, "console"))
829     {
830         if (pid > 0)
831         {
832             char fd_name[256];
833
834             if (xev_trace_fd >= 0)
835                 close (xev_trace_fd);
836
837             snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
838
839             xev_trace_fd = open (fd_name, O_RDWR);
840             if (xev_trace_fd < 0)
841             {
842                 char err_buf[256] = {0,};
843                 char *errp;
844
845                 errp = (char *)strerror_r (errno, err_buf, sizeof(err_buf));
846                 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, errp);
847             }
848
849             pMod->evlog_path = strdup (fd_name);
850         }
851
852         return TRUE;
853     }
854
855     if (path[0] == '/')
856         snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
857     else
858     {
859         if (pMod->cwd)
860             snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
861         else
862             snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
863     }
864
865     pMod->evlog_path = strdup (fd_name);
866
867     fd_check = open (fd_name, O_RDONLY);
868     if(fd_check < 0)
869         init = 0;
870     else
871         close (fd_check);
872
873     xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
874     if (xev_trace_record_fd < 0)
875     {
876         char err_buf[256] = {0,};
877         char *errp;
878
879         errp = (char *)strerror_r (errno, err_buf, sizeof(err_buf));
880         XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, errp);
881         return FALSE;
882     }
883
884     return TRUE;
885 }