mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-01 07:13:42 +02:00
239 lines
4.5 KiB
ObjectPascal
239 lines
4.5 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2003 by the Free Pascal development team
|
|
|
|
Console and system log version of debug server.
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
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.
|
|
|
|
**********************************************************************}
|
|
|
|
{$mode objfpc}
|
|
{$h+}
|
|
|
|
program debugserver;
|
|
|
|
Uses
|
|
msgintf,debugserverintf,baseunix,classes,sysutils,getopts,systemlog;
|
|
|
|
resourcestring
|
|
SUnknownOption = 'Unknown option : %s';
|
|
SMessageFrom = '%s [%s] : %s ';
|
|
|
|
Var
|
|
UseSyslog : Boolean;
|
|
|
|
Const
|
|
LogLevel : Integer = log_debug;
|
|
|
|
Procedure LogEvent(Const Event: TDebugEvent);
|
|
|
|
Var
|
|
S : String;
|
|
|
|
begin
|
|
With Event do
|
|
begin
|
|
S:=DateTimeToStr(TimeStamp)+' : '+Format(SMessageFrom,[MsgTypes[LogCode],Client.Peer,Event]);
|
|
If UseSysLog then
|
|
Syslog(LogLevel,Pchar(S),[])
|
|
else
|
|
Writeln(S);
|
|
end;
|
|
end;
|
|
|
|
Function GetFDS(Var AFDS : tfdset) : Integer;
|
|
|
|
Var
|
|
I : Integer;
|
|
|
|
begin
|
|
Result:=0;
|
|
fpfd_zero(AFDS);
|
|
For I:=0 to FClients.Count-1 do
|
|
With TClient(FClients[i]) do
|
|
begin
|
|
If Handle>Result then
|
|
Result:=Handle;
|
|
fpfd_set(Handle,AFDS);
|
|
end;
|
|
Inc(Result);
|
|
end;
|
|
|
|
Procedure StartReading;
|
|
|
|
Var
|
|
ReadFDS : tfdset;
|
|
I,maxfds : Integer;
|
|
TimeOut : TTimeVal;
|
|
|
|
begin
|
|
Repeat
|
|
maxfds:=GetFDS(ReadFDS);
|
|
TimeOut.tv_sec:=0;
|
|
TimeOut.tv_usec:=10000;
|
|
Maxfds:=fpSelect(maxfds,@ReadFDS,Nil,Nil,@TimeOut);
|
|
If MaxFds>0 then
|
|
begin
|
|
For I:=FClients.Count-1 downto 0 do
|
|
If fpFD_IsSet(TClient(FClients[i]).Handle,ReadFDS)<>0 then
|
|
ReadMessage(TClient(FClients[i]).Handle);
|
|
end;
|
|
// Check for new connection.
|
|
CheckNewConnection;
|
|
Until (FClients.Count=0);
|
|
end;
|
|
|
|
procedure Wait;
|
|
|
|
Var
|
|
TV,TR : TimeSpec;
|
|
|
|
begin
|
|
tv.tv_sec:=1;
|
|
tv.tv_nsec:=0;
|
|
fpnanosleep(@tv,@tr);
|
|
end;
|
|
|
|
Procedure HandleConnections;
|
|
|
|
begin
|
|
Repeat
|
|
If CheckNewConnection<>Nil then
|
|
StartReading
|
|
else
|
|
Wait;
|
|
Until quit;
|
|
end;
|
|
|
|
Var
|
|
OldHUPHandler,
|
|
OldINTHandler,
|
|
OldQUITHandler,
|
|
OldTERMHandler : SigActionRec;
|
|
|
|
Procedure HandleSig(Sig : Longint); Cdecl;
|
|
|
|
Var
|
|
OH : Signalhandler;
|
|
|
|
begin
|
|
Quit:=True;
|
|
Case Sig of
|
|
SIGHUP : OH:=signalhandler(OldHUPHandler.sa_handler);
|
|
SIGTERM : OH:=signalhandler(OldTERMHandler.sa_handler);
|
|
SIGQUIT : OH:=signalhandler(OldQUITHandler.sa_handler);
|
|
SIGINT : OH:=signalhandler(OldINTHandler.sa_handler);
|
|
else
|
|
OH:=Nil;
|
|
end;
|
|
If (OH<>SignalHandler(SIG_DFL)) then
|
|
OH(Sig);
|
|
end;
|
|
|
|
Procedure SetupSignals;
|
|
|
|
Procedure SetupSig (Sig : Longint; Var OH : SigactionRec);
|
|
|
|
Var
|
|
Act : SigActionRec;
|
|
begin
|
|
signalhandler(Act.sa_handler):=@HandleSig;
|
|
fpsigemptyset(act.sa_mask);
|
|
Act.SA_FLAGS:=0;
|
|
|
|
{$ifdef linux} // ???
|
|
Act.Sa_restorer:=Nil;
|
|
{$endif}
|
|
if fpSigAction(Sig,@Act,@OH)=-1 then
|
|
begin
|
|
Writeln(stderr,SErrFailedToSetSignalHandler);
|
|
Halt(1)
|
|
end;
|
|
end;
|
|
begin
|
|
SetupSig(SIGTERM,OldTERMHandler);
|
|
SetupSig(SIGQUIT,OldQUITHandler);
|
|
SetupSig(SIGINT,OldINTHandler);
|
|
SetupSig(SIGHUP,OldHUPHandler);
|
|
end;
|
|
|
|
Procedure Usage;
|
|
|
|
begin
|
|
Writeln('Usage : debugserver [options]');
|
|
Writeln('where options is one of');
|
|
Writeln(' -h this help');
|
|
Writeln(' -s socket use unix socket');
|
|
Writeln(' -l uses syslog instead of standard output');
|
|
Halt(1);
|
|
end;
|
|
|
|
Procedure ProcessOptions;
|
|
|
|
Var
|
|
C : Char;
|
|
I : Integer;
|
|
|
|
begin
|
|
UseSyslog:=False;
|
|
Repeat
|
|
C:=getopt('hl::s:');
|
|
case c of
|
|
'h' : Usage;
|
|
's' : DebugSocket:=OptArg;
|
|
'l' : begin
|
|
UseSysLog:=True;
|
|
LogLevel:=StrToIntdef(OptArg,LogLevel);
|
|
end;
|
|
'?' : begin
|
|
Writeln(Format(SUnknownOption,[OptOpt]));
|
|
Usage;
|
|
end;
|
|
end;
|
|
Until (C=EndOfOptions);
|
|
if OptInd<=ParamCount then
|
|
begin
|
|
For I:=OptInd to ParamCount do
|
|
Writeln(Format(SUnknownOption,[Paramstr(i)]));
|
|
Usage;
|
|
end;
|
|
end;
|
|
|
|
Procedure SetupSysLog;
|
|
|
|
Var
|
|
Prefix : String;
|
|
|
|
begin
|
|
prefix:=format('DebugServer[%d] ',[fpGetPID]);
|
|
OpenLog(pchar(prefix),LOG_NOWAIT,LOG_DEBUG);
|
|
end;
|
|
|
|
Procedure CloseSyslog;
|
|
|
|
begin
|
|
CloseLog;
|
|
end;
|
|
|
|
begin
|
|
ProcessOptions;
|
|
SetupSignals;
|
|
If UseSysLog then
|
|
SetupSyslog;
|
|
OpenDebugServer;
|
|
DebugLogCallback:=@LogEvent;
|
|
Try
|
|
HandleConnections;
|
|
Finally
|
|
CloseDebugServer;
|
|
If UseSyslog then
|
|
CloseSyslog;
|
|
end;
|
|
end.
|