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