debugserver.pp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2003 by the Free Pascal development team
  5. Console and system log version of debug server.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. {$h+}
  14. program debugserver;
  15. Uses
  16. msgintf,debugserverintf,linux,classes,sysutils,getopts,systemlog;
  17. resourcestring
  18. SUnknownOption = 'Unknown option : %s';
  19. SMessageFrom = '%s [%s] : %s ';
  20. Var
  21. UseSyslog : Boolean;
  22. Const
  23. LogLevel : Integer = log_debug;
  24. Procedure LogEvent(Const Event: TDebugEvent);
  25. Var
  26. S : String;
  27. begin
  28. With Event do
  29. begin
  30. S:=DateTimeToStr(TimeStamp)+' : '+Format(SMessageFrom,[MsgTypes[LogCode],Client.Peer,Event]);
  31. If UseSysLog then
  32. Syslog(LogLevel,Pchar(S),[])
  33. else
  34. Writeln(S);
  35. end;
  36. end;
  37. Function GetFDS(Var AFDS : tfdset) : Integer;
  38. Var
  39. I : Integer;
  40. begin
  41. Result:=0;
  42. fd_zero(AFDS);
  43. For I:=0 to FClients.Count-1 do
  44. With TClient(FClients[i]) do
  45. begin
  46. If Handle>Result then
  47. Result:=Handle;
  48. fd_set(Handle,AFDS);
  49. end;
  50. Inc(Result);
  51. end;
  52. Procedure StartReading;
  53. Var
  54. ReadFDS : tfdset;
  55. I,maxfds : Integer;
  56. TimeOut : TTimeVal;
  57. begin
  58. Repeat
  59. maxfds:=GetFDS(ReadFDS);
  60. TimeOut.sec:=0;
  61. TimeOut.usec:=10000;
  62. Maxfds:=Select(maxfds,@ReadFDS,Nil,Nil,@TimeOut);
  63. If MaxFds>0 then
  64. begin
  65. For I:=FClients.Count-1 downto 0 do
  66. If FD_IsSet(TClient(FClients[i]).Handle,ReadFDS) then
  67. ReadMessage(TClient(FClients[i]).Handle);
  68. end;
  69. // Check for new connection.
  70. CheckNewConnection;
  71. Until (FClients.Count=0);
  72. end;
  73. procedure Wait;
  74. Var
  75. TV,TR : TimeSpec;
  76. begin
  77. tv.tv_sec:=1;
  78. tv.tv_nsec:=0;
  79. nanosleep(tv,tr);
  80. end;
  81. Procedure HandleConnections;
  82. begin
  83. Repeat
  84. If CheckNewConnection<>Nil then
  85. StartReading
  86. else
  87. Wait;
  88. Until quit;
  89. end;
  90. Var
  91. OldHUPHandler,
  92. OldINTHandler,
  93. OldQUITHandler,
  94. OldTERMHandler : SigActionRec;
  95. Procedure HandleSig(Sig : Longint); Cdecl;
  96. Var
  97. OH : SignalHandler;
  98. begin
  99. Quit:=True;
  100. Case Sig of
  101. SIGHUP : OH:=OldHUPHandler.handler.sh;
  102. SIGTERM : OH:=OldTERMHandler.handler.sh;
  103. SIGQUIT : OH:=OldQUITHandler.handler.sh;
  104. SIGINT : OH:=OldINTHandler.handler.sh;
  105. else
  106. OH:=Nil;
  107. end;
  108. If (OH<>SignalHandler(SIG_DFL)) then
  109. OH(Sig);
  110. end;
  111. Procedure SetupSignals;
  112. Procedure SetupSig (Sig : Longint; Var OH : SigactionRec);
  113. Var
  114. Act : SigActionRec;
  115. begin
  116. Act.handler.sh:=@HandleSig;
  117. Act.sa_mask:=0;
  118. Act.SA_FLAGS:=0;
  119. Act.Sa_restorer:=Nil;
  120. SigAction(Sig,@Act,@OH);
  121. If LinuxError<>0 then
  122. begin
  123. Writeln(stderr,SErrFailedToSetSignalHandler);
  124. Halt(1)
  125. end;
  126. end;
  127. begin
  128. SetupSig(SIGTERM,OldTERMHandler);
  129. SetupSig(SIGQUIT,OldQUITHandler);
  130. SetupSig(SIGINT,OldINTHandler);
  131. SetupSig(SIGHUP,OldHUPHandler);
  132. end;
  133. Procedure Usage;
  134. begin
  135. Writeln('Usage : debugserver [options]');
  136. Writeln('where options is one of');
  137. Writeln(' -h this help');
  138. Writeln(' -s socket use unix socket');
  139. Writeln(' -l uses syslog instead of standard output');
  140. Halt(1);
  141. end;
  142. Procedure ProcessOptions;
  143. Var
  144. C : Char;
  145. I : Integer;
  146. begin
  147. UseSyslog:=False;
  148. Repeat
  149. C:=getopt('hl::s:');
  150. case c of
  151. 'h' : Usage;
  152. 's' : DebugSocket:=OptArg;
  153. 'l' : begin
  154. UseSysLog:=True;
  155. LogLevel:=StrToIntdef(OptArg,LogLevel);
  156. end;
  157. '?' : begin
  158. Writeln(Format(SUnknownOption,[OptOpt]));
  159. Usage;
  160. end;
  161. end;
  162. Until (C=EndOfOptions);
  163. if OptInd<=ParamCount then
  164. begin
  165. For I:=OptInd to ParamCount do
  166. Writeln(Format(SUnknownOption,[Paramstr(i)]));
  167. Usage;
  168. end;
  169. end;
  170. Procedure SetupSysLog;
  171. Var
  172. Prefix : String;
  173. begin
  174. prefix:=format('DebugServer[%d] ',[GetPID]);
  175. OpenLog(pchar(prefix),LOG_NOWAIT,LOG_DEBUG);
  176. end;
  177. Procedure CloseSyslog;
  178. begin
  179. CloseLog;
  180. end;
  181. begin
  182. ProcessOptions;
  183. SetupSignals;
  184. If UseSysLog then
  185. SetupSyslog;
  186. OpenDebugServer;
  187. DebugLogCallback:=@LogEvent;
  188. Try
  189. HandleConnections;
  190. Finally
  191. CloseDebugServer;
  192. If UseSyslog then
  193. CloseSyslog;
  194. end;
  195. end.