00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <ptlib.h>
00035 #include <ptlib/sockets.h>
00036
00037 #include <list>
00038
00039
00051 class PCLI : public PObject
00052 {
00053 PCLASSINFO(PCLI, PObject);
00054 public:
00055 class Context;
00056
00059 class Context : public PIndirectChannel
00060 {
00061 public:
00066 Context(
00067 PCLI & cli
00068 );
00069
00073 virtual ~Context();
00075
00092 virtual PBoolean Write(
00093 const void * buf,
00094 PINDEX len
00095 );
00097
00102 bool Start();
00103
00107 void Stop();
00108
00114 virtual void OnStart();
00115
00121 virtual void OnStop();
00122
00126 virtual bool ReadAndProcessInput();
00127
00130 virtual void ProcessInput(char ch);
00131
00138 virtual void OnCompletedLine();
00140
00145 PCLI & GetCLI() const { return m_cli; }
00146
00149 bool IsProcessingCommand() const { return m_processingCommand; }
00151
00152 protected:
00153 PDECLARE_NOTIFIER(PThread, Context, ThreadMain);
00154
00155 PCLI & m_cli;
00156 PString m_commandLine;
00157 bool m_ignoreNextLF;
00158 PStringList m_commandHistory;
00159 PThread * m_thread;
00160 bool m_processingCommand;
00161 };
00162
00165 class Arguments : public PArgList
00166 {
00167 public:
00170 Arguments(
00171 Context & context,
00172 const PString & rawLine
00173 );
00175
00180 Context & WriteUsage();
00181
00184 Context & WriteError(
00185 const PString & error = PString::Empty()
00186 );
00188
00193 Context & GetContext() const { return m_context; }
00195
00196 protected:
00197 Context & m_context;
00198 PString m_command;
00199 PString m_usage;
00200
00201 friend class PCLI;
00202 };
00203
00204
00209 PCLI(
00210 const char * prompt = NULL
00211 );
00212
00216 virtual ~PCLI();
00218
00229 virtual bool Start(
00230 bool runInBackground = true
00231 );
00232
00237 virtual void Stop();
00238
00241 bool StartContext(
00242 PChannel * channel,
00243 bool autoDelete = true,
00244 bool runInBackground = true
00245 );
00246 bool StartContext(
00247 PChannel * readChannel,
00248 PChannel * writeChannel,
00249 bool autoDeleteRead = true,
00250 bool autoDeleteWrite = true,
00251 bool runInBackground = true
00252 );
00253
00257 virtual Context * CreateContext();
00258
00262 virtual Context * AddContext(
00263 Context * context = NULL
00264 );
00265
00269 virtual void RemoveContext(
00270 Context * context
00271 );
00272
00275 virtual void GarbageCollection();
00276
00284 virtual void OnReceivedLine(
00285 Arguments & line
00286 );
00287
00290 void Broadcast(
00291 const PString & message
00292 ) const;
00293
00304 bool SetCommand(
00305 const char * command,
00306 const PNotifier & notifier,
00307 const char * help = NULL,
00308 const char * usage = NULL
00309 );
00310
00313 void ShowHelp(
00314 Context & context
00315 );
00317
00323 const PString & GetPrompt() const { return m_prompt; }
00324
00328 void SetPrompt(const PString & prompt) { m_prompt = prompt; }
00329
00333 const PString & GetNewLine() const { return m_newLine; }
00334
00338 void SetNewLine(const PString & newLine) { m_newLine = newLine; }
00339
00343 const PCaselessString & GetHelpCommand() const { return m_helpCommand; }
00344
00348 void SetHelpCommand(const PCaselessString & helpCommand) { m_helpCommand = helpCommand; }
00349
00352 const PString & GetHelpOnHelp() const { return m_helpOnHelp; }
00353
00356 void SetHelpOnHelp(const PCaselessString & helpOnHelp) { m_helpOnHelp = helpOnHelp; }
00357
00361 const PCaselessString & GetRepeatCommand() const { return m_repeatCommand; }
00362
00366 void SetRepeatCommand(const PCaselessString & repeatCommand) { m_repeatCommand = repeatCommand; }
00367
00371 const PCaselessString & GetHistoryCommand() const { return m_historyCommand; }
00372
00376 void SetHistoryCommand(const PCaselessString & historyCommand) { m_historyCommand = historyCommand; }
00377
00380 const PString & GetNoHistoryError() const { return m_noHistoryError; }
00381
00384 void SetNoHistoryError(const PString & noHistoryError) { m_noHistoryError = noHistoryError; }
00385
00388 const PString & GetCommandUsagePrefix() const { return m_commandUsagePrefix; }
00389
00392 void SetCommandUsagePrefix(const PString & commandUsagePrefix) { m_commandUsagePrefix = commandUsagePrefix; }
00393
00396 const PString & GetCommandErrorPrefix() const { return m_commandErrorPrefix; }
00397
00400 void SetCommandErrorPrefix(const PString & commandErrorPrefix) { m_commandErrorPrefix = commandErrorPrefix; }
00401
00404 const PString & GetUnknownCommandError() const { return m_unknownCommandError; }
00405
00408 void SetUnknownCommandError(const PString & unknownCommandError) { m_unknownCommandError = unknownCommandError; }
00410
00411 protected:
00412 PString m_prompt;
00413 PString m_newLine;
00414 PCaselessString m_helpCommand;
00415 PString m_helpOnHelp;
00416 PCaselessString m_repeatCommand;
00417 PCaselessString m_historyCommand;
00418 PString m_noHistoryError;
00419 PString m_commandUsagePrefix;
00420 PString m_commandErrorPrefix;
00421 PString m_unknownCommandError;
00422
00423 struct InternalCommand {
00424 PNotifier m_notifier;
00425 PString m_help;
00426 PString m_usage;
00427 };
00428 typedef std::map<PString, InternalCommand> CommandMap_t;
00429 CommandMap_t m_commands;
00430
00431 typedef std::list<Context *> ContextList_t;
00432 ContextList_t m_contextList;
00433 PMutex m_contextMutex;
00434 };
00435
00436
00439 class PCLIStandard : public PCLI
00440 {
00441 public:
00446 PCLIStandard(
00447 const char * prompt = NULL
00448 );
00450
00457 virtual bool Start(
00458 bool runInBackground = true
00459 );
00461 };
00462
00463
00468 class PCLISocket : public PCLI
00469 {
00470 public:
00473 PCLISocket(
00474 WORD port = 0,
00475 const char * prompt = NULL,
00476 bool singleThreadForAll = false
00477 );
00478 ~PCLISocket();
00480
00487 virtual bool Start(
00488 bool runInBackground = true
00489 );
00490
00498 virtual void Stop();
00499
00503 virtual Context * AddContext(
00504 Context * context = NULL
00505 );
00506
00510 virtual void RemoveContext(
00511 Context * context
00512 );
00514
00519 bool Listen(
00520 WORD port = 0
00521 );
00522
00525 WORD GetPort() const { return m_listenSocket.GetPort(); }
00526
00527 protected:
00528 PDECLARE_NOTIFIER(PThread, PCLISocket, ThreadMain);
00529 bool HandleSingleThreadForAll();
00530 bool HandleIncoming();
00531
00532 bool m_singleThreadForAll;
00533
00534 PTCPSocket m_listenSocket;
00535 PThread * m_thread;
00536
00537 typedef std::map<PSocket *, Context *> ContextMap_t;
00538 ContextMap_t m_contextBySocket;
00539 };