ignore the root window at XDbgLogSetWindowPixmap
[platform/adaptation/xf86-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 #define FP1616toDBL(x) ((x) * 1.0 / (1 << 16))
71
72 Bool        xev_trace_on = FALSE;
73 int         xev_trace_detail_level = EVLOG_PRINT_DEFAULT;
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 = NULL;
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 = NULL;
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             if (err)
355             {
356                 evinfo.mask |= EVLOG_MASK_ERROR;
357                 evinfo.err.errorCode = err->errorCode;
358                 evinfo.err.resourceID = err->resourceID;
359                 evinfo.err.minorCode = err->minorCode;
360                 evinfo.err.majorCode = err->majorCode;
361             }
362             else
363                 XDBG_NEVER_GET_HERE (MXDBG);
364         }
365     }
366
367     /* evinfo.evt */
368     if (ev)
369     {
370         if (type == EVENT)
371         {
372             evinfo.mask |= EVLOG_MASK_EVENT;
373             evinfo.evt.ptr = ev;
374             snprintf (evinfo.evt.name, sizeof (evinfo.evt.name), "%s",
375                       LookupEventName ((int)(ev->u.u.type)));
376         }
377     }
378
379     /* evinfo.time */
380     evinfo.time = GetTimeInMillis ();
381
382     /* get extension entry */
383     if (!EntryInit && !xDbgEvlogGetExtensionEntry())
384         return;
385
386     EntryInit = 1;
387
388     if (!xDbgEvlogRuleValidate (&evinfo))
389         return;
390
391     if (xev_trace_record_fd >= 0)
392     {
393         if (xDbgEvlogFillLog (&evinfo, EVLOG_PRINT_REPLY_DETAIL, NULL, NULL))
394             evtRecord (xev_trace_record_fd, &evinfo);
395     }
396     else
397     {
398         char log[1024];
399         int size = sizeof (log);
400
401         if (xDbgEvlogFillLog (&evinfo, xev_trace_detail_level, log, &size))
402             evtPrintF (xev_trace_fd, &evinfo, log);
403     }
404
405     /* evatom initialize */
406     xDbgDistroyAtomList(&evinfo);
407     xDbgDistroyRegionList(&evinfo);
408 }
409
410 #ifdef _SECURE_LOG
411 static const char*
412 _traceGetWindowName (ClientPtr client, Window window)
413 {
414     int rc;
415     WindowPtr pWin;
416     Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
417     Atom property;
418     PropertyPtr pProp;
419     static char winname[128];
420     int datalen;
421
422     rc = dixLookupWindow (&pWin, window, client, win_mode);
423     if (rc != Success)
424         return NULL;
425
426     property = MakeAtom ("WM_NAME", strlen ("WM_NAME"), TRUE);
427     while (pWin)
428     {
429         rc = dixLookupProperty (&pProp, pWin, property, client, prop_mode);
430         if (rc == Success && pProp->data)
431         {
432             datalen = (pProp->size>127) ?127:pProp->size;
433             strncpy (winname, pProp->data, datalen);
434             winname[datalen] = 0;
435
436             return winname;
437         }
438
439         pWin = pWin->parent;
440     }
441
442     return NULL;
443 }
444 #endif
445
446 static void
447 _traceFlush (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
448 {
449     if (xev_trace_on == FALSE)
450         return;
451
452     evtPrint (FLUSH, NULL, NULL, NULL);
453 }
454
455 static void
456 _traceAReply (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
457 {
458     if (xev_trace_on == FALSE)
459         return;
460
461     ReplyInfoRec *pri = (ReplyInfoRec*)calldata;
462
463     evtPrint (REPLY, pri->client, NULL, pri);
464 }
465
466 static void
467 _traceEvent (CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
468 {
469     EventInfoRec *pei = (EventInfoRec*)calldata;
470     ClientPtr pClient;
471     ModuleClientInfo *info;
472     int ev; /* event index */
473     static int xi2_opcode = -1;
474     xEvent *pev;
475
476 #ifdef _SECURE_LOG
477     static char* ename[]=
478     {
479         "KeyPress",
480         "KeyRelease",
481         "ButtonPress",
482         "ButtonRelease",
483     };
484 #endif
485
486     XDBG_RETURN_IF_FAIL (pei != NULL);
487
488     pClient = pei->client;
489     XDBG_RETURN_IF_FAIL (pClient != NULL);
490
491     pev = pei->events;
492     XDBG_RETURN_IF_FAIL (pev != NULL);
493
494     info = GetClientInfo (pClient);
495     XDBG_RETURN_IF_FAIL (info != NULL);
496
497     for (ev=0; ev < pei->count; ev++, pev++)
498     {
499         int type = pev->u.u.type & 0177;
500
501         if (type < LASTEvent)
502         {
503             switch (type)
504             {
505             case KeyPress:
506             case KeyRelease:
507                 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%x) 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), (unsigned int)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
515             case ButtonPress:
516             case ButtonRelease:
517                 XDBG_SECURE (MXDBG, "%s(%d)_%d(%s.%d : %s.0x%x) root(%d,%d) win(%d,%d)\n"
518                         , ename[type-KeyPress], pev->u.u.detail, pev->u.u.type
519                         , info->command, info->pid
520                         , _traceGetWindowName (pClient, pev->u.keyButtonPointer.event), (unsigned int)pev->u.keyButtonPointer.event
521                         , pev->u.keyButtonPointer.rootX, pev->u.keyButtonPointer.rootY
522                         , pev->u.keyButtonPointer.eventX, pev->u.keyButtonPointer.eventY);
523                 break;
524             case GenericEvent:
525                 if(!xi2_opcode) break;
526                 if(xi2_opcode < 0)
527                 {
528                     ExtensionEntry *pExt = CheckExtension("XInputExtension");
529                     if(!pExt) xi2_opcode = 0;
530                     else xi2_opcode = pExt->base;
531                 }
532
533                 if(((xGenericEvent*)pev)->extension != xi2_opcode) break;
534
535                 xXIDeviceEvent *xidev = (xXIDeviceEvent *)pev;
536                 if(xidev->deviceid==2) break;
537                 if(xidev->evtype==XI_ButtonPress)
538                     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));
539                 else if(xidev->evtype==XI_ButtonRelease)
540                     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));
541                 else if(xidev->evtype==XI_Motion)
542                     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));
543                 break;
544             default:
545                 break;
546             }
547         }
548
549         if (type != X_Error && xev_trace_on)
550             evtPrint (EVENT, pClient, pev, NULL);
551         else if (type == X_Error && xev_trace_on)
552             evtPrint (ERROR, pClient, pev, NULL);
553     }
554 }
555
556 static void
557 _traceACoreEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
558 {
559     if (xev_trace_on == FALSE)
560         return;
561
562     XaceCoreDispatchRec *rec = calldata;
563
564     XDBG_RETURN_IF_FAIL (rec != NULL);
565
566     evtPrint (REQUEST, rec->client, NULL, NULL);
567 }
568
569 static void
570 _traceAExtEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
571 {
572     if (xev_trace_on == FALSE)
573         return;
574
575     XaceExtAccessRec *rec = calldata;
576
577     XDBG_RETURN_IF_FAIL (rec != NULL);
578
579     evtPrint (REQUEST, rec->client, NULL, NULL);
580 }
581
582 static void
583 _traceAuditEndEvents (CallbackListPtr *pcbl, pointer unused, pointer calldata)
584 {
585     return;
586 }
587
588 static void
589 _traceProperty (CallbackListPtr *pcbl, pointer unused, pointer calldata)
590 {
591     XacePropertyAccessRec *rec = calldata;
592     ModuleClientInfo *info = GetClientInfo (rec->client);
593     PropertyPtr pProp = *rec->ppProp;
594     Atom name = pProp->propertyName;
595
596     /* Don't care about the new content check */
597     if (rec->client == serverClient || rec->access_mode & DixPostAccess)
598         return;
599
600     if (name == atom_client_pid && (rec->access_mode & DixWriteAccess))
601     {
602         XDBG_WARNING (MXDBG, "Invalid access X_CLINET_PID pid:%d, uid:%d\n", info->pid, info->uid);
603         rec->status = BadAccess;
604         return;
605     }
606
607     rec->status = Success;
608     return;
609 }
610
611 static void
612 _traceResource (CallbackListPtr *pcbl, pointer unused, pointer calldata)
613 {
614     XaceResourceAccessRec *rec = calldata;
615     Mask access_mode = rec->access_mode;
616     ModuleClientInfo *info = GetClientInfo (rec->client);
617
618     /* Perform the background none check on windows */
619     if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW)
620     {
621         WindowPtr pWin = (WindowPtr) rec->res;
622         int rc;
623         int pid = info->pid;
624
625         rc = dixChangeWindowProperty (serverClient,
626                                       pWin, atom_client_pid, XA_CARDINAL, 32,
627                                       PropModeReplace, 1, &pid, FALSE);
628         if (rc != Success)
629             XDBG_ERROR (MXDBG, "failed : set X_CLIENT_PID to %d.\n", pid);
630     }
631 }
632
633 static void
634 _traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata)
635 {
636     XaceReceiveAccessRec *rec = calldata;
637
638     if (rec->events->u.u.type != VisibilityNotify)
639         return;
640
641     rec->status = BadAccess;
642 }
643
644 Bool
645 xDbgModuleEvlogInstallHooks (XDbgModule *pMod)
646 {
647     int ret = TRUE;
648
649     ret &= AddCallback (&EventCallback, _traceEvent, NULL);
650     ret &= XaceRegisterCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
651     ret &= XaceRegisterCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
652
653     /*Disable Visibility Event*/
654     ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL);
655
656     if (atom_client_pid == None)
657         atom_client_pid = MakeAtom ("X_CLIENT_PID", 12, TRUE);
658     if (atom_rotate == None)
659         atom_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE", 12, TRUE);
660
661     if (!ret)
662     {
663         XDBG_ERROR (MXDBG, "failed: register one or more callbacks\n");
664         return FALSE;
665     }
666
667     if (pMod && pMod->evlog_path)
668         xDbgModuleEvlogSetEvlogPath (pMod, -1, pMod->evlog_path, NULL, NULL);
669
670     return TRUE;
671 }
672
673 void
674 xDbgModuleEvlogUninstallHooks (XDbgModule *pMod)
675 {
676     DeleteCallback (&EventCallback, _traceEvent, NULL);
677     XaceDeleteCallback (XACE_PROPERTY_ACCESS, _traceProperty, NULL);
678     XaceDeleteCallback (XACE_RESOURCE_ACCESS, _traceResource, NULL);
679 }
680
681 void
682 xDbgModuleEvlogPrintEvents (XDbgModule *pMod, Bool on, const char * client_name, char *reply, int *len)
683 {
684     int ret = TRUE;
685
686     on = (on)?TRUE:FALSE;
687     if (xev_trace_on == on)
688         return;
689
690     xev_trace_on = on;
691
692     if (xev_trace_on)
693     {
694         int i;
695
696         //Find client's pid
697         for (i=1 ; i< currentMaxClients ; i++)
698         {
699             ClientPtr pClient;
700             ModuleClientInfo *info;
701
702             pClient = clients[i];
703             if (!pClient)
704                 continue;
705
706             info = GetClientInfo (pClient);
707             if (!info)
708                 continue;
709
710             if (strlen (info->command) > 0 && strstr (client_name, info->command))
711             {
712                 char fd_name[256];
713
714                 if (xev_trace_fd >= 0)
715                     close (xev_trace_fd);
716
717                 snprintf (fd_name, 256, "/proc/%d/fd/1", info->pid);
718                 xev_trace_fd = open (fd_name, O_RDWR);
719                 if (xev_trace_fd < 0)
720                     XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
721             }
722         }
723
724         ret &= AddCallback (&FlushCallback, _traceFlush, NULL);
725         ret &= AddCallback (&ReplyCallback, _traceAReply, NULL);
726         ret &= XaceRegisterCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
727         ret &= XaceRegisterCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
728         ret &= XaceRegisterCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
729
730         if (!ret)
731         {
732             XDBG_REPLY ("failed: register one or more callbacks.\n");
733             return;
734         }
735     }
736     else
737     {
738         DeleteCallback (&FlushCallback, _traceFlush, NULL);
739         DeleteCallback (&ReplyCallback, _traceAReply, NULL);
740         XaceDeleteCallback (XACE_CORE_DISPATCH, _traceACoreEvents, NULL);
741         XaceDeleteCallback (XACE_EXT_DISPATCH, _traceAExtEvents, NULL);
742         XaceDeleteCallback (XACE_AUDIT_END, _traceAuditEndEvents, NULL);
743     }
744
745     return;
746 }
747
748 void
749 xDbgModuleEvlogDetail (XDbgModule *pMod, int level, char *reply, int *len)
750 {
751     xev_trace_detail_level = level;
752 }
753
754 int
755 xDbgModuleEvlogInfoSetRule (XDbgModule *pMod, const int argc, const char ** argv, char *reply, int *len)
756 {
757     return xDbgEvlogRuleSet (argc, argv, reply, len);
758 }
759
760 Bool
761 xDbgModuleEvlogSetEvlogPath (XDbgModule *pMod, int pid, char *path, char *reply, int *len)
762 {
763     char fd_name[XDBG_PATH_MAX];
764     int  fd_check = -1;
765
766     if (!path || strlen (path) <= 0)
767     {
768         XDBG_REPLY ("failed: invalid path\n");
769         return FALSE;
770     }
771
772     if (xev_trace_record_fd >= 0)
773     {
774         close (xev_trace_record_fd);
775         xev_trace_record_fd = -1;
776     }
777
778     if (!strcmp (path, "console"))
779     {
780         if (pid > 0)
781         {
782             char fd_name[256];
783
784             if (xev_trace_fd >= 0)
785                 close (xev_trace_fd);
786
787             snprintf (fd_name, sizeof (fd_name), "/proc/%d/fd/1", pid);
788
789             xev_trace_fd = open (fd_name, O_RDWR);
790             if (xev_trace_fd < 0)
791                 XDBG_REPLY ("failed: open consol '%s'. (%s)\n", fd_name, strerror(errno));
792         }
793
794         return TRUE;
795     }
796
797     if (path[0] == '/')
798         snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
799     else
800     {
801         if (pMod->cwd)
802             snprintf (fd_name, XDBG_PATH_MAX, "%s/%s", pMod->cwd, path);
803         else
804             snprintf (fd_name, XDBG_PATH_MAX, "%s", path);
805     }
806
807     fd_check = open (fd_name, O_RDONLY);
808     if(fd_check < 0)
809         init = 0;
810     else
811         close (fd_check);
812
813     xev_trace_record_fd = open (fd_name, O_CREAT|O_RDWR|O_APPEND, 0755);
814     if (xev_trace_record_fd < 0)
815     {
816         XDBG_REPLY ("failed: open file '%s'. (%s)\n", fd_name, strerror(errno));
817         return FALSE;
818     }
819
820     return TRUE;
821 }