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