debugserver.pp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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,baseunix,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. fpfd_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. fpfd_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.tv_sec:=0;
  60. TimeOut.tv_usec:=10000;
  61. Maxfds:=fpSelect(maxfds,@ReadFDS,Nil,Nil,@TimeOut);
  62. If MaxFds>0 then
  63. begin
  64. For I:=FClients.Count-1 downto 0 do
  65. If fpFD_IsSet(TClient(FClients[i]).Handle,ReadFDS)<>0 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. fpnanosleep(@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:=signalhandler(OldHUPHandler.sa_handler);
  101. SIGTERM : OH:=signalhandler(OldTERMHandler.sa_handler);
  102. SIGQUIT : OH:=signalhandler(OldQUITHandler.sa_handler);
  103. SIGINT : OH:=signalhandler(OldINTHandler.sa_handler);
  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. signalhandler(Act.sa_handler):=@HandleSig;
  116. fpsigemptyset(act.sa_mask);
  117. Act.SA_FLAGS:=0;
  118. {$ifdef linux} // ???
  119. Act.Sa_restorer:=Nil;
  120. {$endif}
  121. if fpSigAction(Sig,@Act,@OH)=-1 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] ',[fpGetPID]);
  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.