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