debugserver.pp 4.4 KB

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