2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
|
|
|
CDebug.c
|
|
|
|
|
2009-08-17 12:41:51 +02:00
|
|
|
(c) 2000-2009 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2009-08-17 12:41:51 +02:00
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 17:41:49 +01:00
|
|
|
any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#define __CDEBUG_C
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "gb_limit.h"
|
2009-08-01 23:28:50 +02:00
|
|
|
#include "gb.debug.h"
|
2007-12-30 17:41:49 +01:00
|
|
|
#include "CDebug.h"
|
|
|
|
|
|
|
|
/*#define DEBUG*/
|
|
|
|
|
|
|
|
|
|
|
|
DECLARE_EVENT(EVENT_Read);
|
|
|
|
|
|
|
|
static int _started = FALSE;
|
2008-01-23 20:56:18 +01:00
|
|
|
static int _fdr = -1;
|
|
|
|
static int _fdw = -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
static CDEBUG *_debug_object = NULL;
|
|
|
|
|
2009-08-01 17:13:50 +02:00
|
|
|
#define BUFFER_SIZE DEBUG_OUTPUT_MAX_SIZE
|
2007-12-30 17:41:49 +01:00
|
|
|
static char *_buffer = NULL;
|
|
|
|
static int _buffer_left;
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
static void callback_read(int fd, int type, intptr_t param)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
int n, i, p;
|
|
|
|
|
2010-03-07 18:14:54 +01:00
|
|
|
for(;;)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2010-03-25 03:00:55 +01:00
|
|
|
fcntl(_fdr, F_SETFL, fcntl(_fdr, F_GETFL) | O_NONBLOCK);
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
if (_buffer_left)
|
|
|
|
{
|
|
|
|
n = read(_fdr, &_buffer[_buffer_left], BUFFER_SIZE - _buffer_left);
|
|
|
|
if (n < 0)
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
n += _buffer_left;
|
|
|
|
_buffer_left = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
n = read(_fdr, _buffer, BUFFER_SIZE);
|
|
|
|
|
|
|
|
if (n <= 0)
|
2010-02-28 18:26:00 +01:00
|
|
|
{
|
2010-03-07 18:14:54 +01:00
|
|
|
//usleep(10000); // the callback is called again and again even if there is nothing to read, why?
|
2007-12-30 17:41:49 +01:00
|
|
|
break;
|
2010-02-28 18:26:00 +01:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
p = 0;
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
if (_buffer[i] == '\n')
|
|
|
|
{
|
|
|
|
/*fprintf(stderr, "CDEBUG_read: <<< %.*s >>>\n", i - p, &_buffer[p]);*/
|
|
|
|
GB.Raise(_debug_object, EVENT_Read, 1, GB_T_STRING, i <= p ? NULL : &_buffer[p], i - p);
|
|
|
|
if (!_buffer)
|
2010-03-25 03:00:55 +01:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
p = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p == 0 && n >= BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
GB.Raise(_debug_object, EVENT_Read, 1, GB_T_STRING, _buffer, BUFFER_SIZE);
|
|
|
|
if (!_buffer)
|
2010-03-07 18:14:54 +01:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
_buffer_left = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_buffer_left = n - p;
|
|
|
|
if (p && n > p)
|
|
|
|
memmove(_buffer, &_buffer[p], _buffer_left);
|
|
|
|
}
|
|
|
|
}
|
2010-03-07 18:14:54 +01:00
|
|
|
|
|
|
|
fcntl(_fdr, F_SETFL, fcntl(_fdr, F_GETFL) & ~O_NONBLOCK);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
// static void callback_read(int fd, int type, intptr_t param)
|
2007-12-30 17:41:49 +01:00
|
|
|
// {
|
|
|
|
// char *buffer = NULL;
|
|
|
|
// char tmp[256];
|
|
|
|
// int n;
|
|
|
|
//
|
|
|
|
// for(;;)
|
|
|
|
// {
|
|
|
|
// n = read(_fdr, tmp, 256);
|
|
|
|
// if (n <= 0)
|
|
|
|
// break;
|
|
|
|
// GB.AddString(&buffer, tmp, n);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// GB.Raise(_debug_object, EVENT_Read, 1, GB_T_STRING, buffer, GB.StringLength(buffer));
|
|
|
|
// }
|
|
|
|
|
|
|
|
static char *input_fifo(char *path)
|
|
|
|
{
|
|
|
|
sprintf(path, "/tmp/gambas.%d/%d.in", getuid(), getpid());
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *output_fifo(char *path)
|
|
|
|
{
|
|
|
|
sprintf(path, "/tmp/gambas.%d/%d.out", getuid(), getpid());
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CDEBUG_begin)
|
|
|
|
|
2010-01-28 11:55:24 +01:00
|
|
|
char path[PATH_MAX];
|
2009-05-22 16:52:36 +02:00
|
|
|
char name[16];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
input_fifo(path);
|
|
|
|
unlink(path);
|
|
|
|
if (mkfifo(path, 0600))
|
|
|
|
{
|
2008-02-02 11:54:13 +01:00
|
|
|
GB.Error("Cannot create input fifo in /tmp: &1", strerror(errno));
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
output_fifo(path);
|
|
|
|
unlink(path);
|
|
|
|
if (mkfifo(path, 0600))
|
|
|
|
{
|
2008-02-02 11:54:13 +01:00
|
|
|
GB.Error("Cannot create output fifo in /tmp: &1", strerror(errno));
|
2007-12-30 17:41:49 +01:00
|
|
|
return;
|
|
|
|
}
|
2009-05-22 16:52:36 +02:00
|
|
|
|
|
|
|
sprintf(name, "%d", getpid());
|
|
|
|
GB.ReturnNewZeroString(name);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CDEBUG_start)
|
|
|
|
|
2010-01-28 11:55:24 +01:00
|
|
|
char path[DEBUG_FIFO_PATH_MAX];
|
2009-01-28 01:22:26 +01:00
|
|
|
int i;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (_started)
|
|
|
|
return;
|
|
|
|
|
2009-05-22 21:20:33 +02:00
|
|
|
for (i = 0; i < 25; i++)
|
2009-01-28 01:22:26 +01:00
|
|
|
{
|
|
|
|
_fdw = open(output_fifo(path), O_WRONLY | O_NONBLOCK);
|
|
|
|
if (_fdw >= 0)
|
|
|
|
break;
|
2009-05-22 21:20:33 +02:00
|
|
|
usleep(20000);
|
2009-01-28 01:22:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_fdw < 0)
|
|
|
|
{
|
|
|
|
GB.Error("Unable to open fifo");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
_fdr = open(input_fifo(path), O_RDONLY | O_NONBLOCK);
|
2010-03-07 18:14:54 +01:00
|
|
|
fcntl(_fdr, F_SETFL, fcntl(_fdr, F_GETFL) & ~O_NONBLOCK);
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
GB.New(POINTER(&_debug_object), GB.FindClass("Debug"), "Debug", NULL);
|
|
|
|
GB.Ref(_debug_object);
|
|
|
|
|
|
|
|
GB.Alloc(POINTER(&_buffer), BUFFER_SIZE);
|
|
|
|
_buffer_left = 0;
|
|
|
|
|
|
|
|
GB.Watch(_fdr, GB_WATCH_READ, (void *)callback_read, 0);
|
|
|
|
|
|
|
|
_started = TRUE;
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CDEBUG_stop)
|
|
|
|
|
|
|
|
if (!_started)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GB.Watch(_fdr, GB_WATCH_NONE, (void *)callback_read, 0);
|
|
|
|
GB.Free(POINTER(&_buffer));
|
|
|
|
|
|
|
|
GB.Unref(POINTER(&_debug_object));
|
|
|
|
|
|
|
|
close(_fdw);
|
|
|
|
close(_fdr);
|
|
|
|
|
2008-01-23 20:56:18 +01:00
|
|
|
_fdw = _fdr = -1;
|
2007-12-30 17:41:49 +01:00
|
|
|
_started = FALSE;
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CDEBUG_end)
|
|
|
|
|
2010-01-28 11:55:24 +01:00
|
|
|
char path[DEBUG_FIFO_PATH_MAX];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
CALL_METHOD_VOID(CDEBUG_stop);
|
|
|
|
|
|
|
|
unlink(input_fifo(path));
|
|
|
|
unlink(output_fifo(path));
|
|
|
|
|
|
|
|
signal(SIGPIPE, SIG_DFL);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD(CDEBUG_write, GB_STRING data)
|
|
|
|
|
2008-01-23 20:56:18 +01:00
|
|
|
if (_fdw < 0)
|
|
|
|
return;
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
if (STRING(data))
|
|
|
|
write(_fdw, STRING(data), LENGTH(data));
|
|
|
|
write(_fdw, "\n", 1);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GB_DESC CDebugDesc[] =
|
|
|
|
{
|
|
|
|
GB_DECLARE("Debug", sizeof(CDEBUG)),
|
|
|
|
GB_NOT_CREATABLE(),
|
|
|
|
|
|
|
|
GB_STATIC_METHOD("_exit", NULL, CDEBUG_end, NULL),
|
|
|
|
|
2009-05-22 16:52:36 +02:00
|
|
|
GB_STATIC_METHOD("Begin", "s", CDEBUG_begin, NULL),
|
2007-12-30 17:41:49 +01:00
|
|
|
GB_STATIC_METHOD("End", NULL, CDEBUG_end, NULL),
|
|
|
|
GB_STATIC_METHOD("Start", NULL, CDEBUG_start, NULL),
|
|
|
|
GB_STATIC_METHOD("Stop", NULL, CDEBUG_stop, NULL),
|
|
|
|
|
|
|
|
GB_STATIC_METHOD("Write", NULL, CDEBUG_write, "(Data)s"),
|
2009-05-22 16:52:36 +02:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
GB_EVENT("Read", NULL, "(Data)s", &EVENT_Read),
|
|
|
|
|
|
|
|
GB_END_DECLARE
|
|
|
|
};
|
|
|
|
|