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
00035
00036 #ifndef PTLIB_CLI_H
00037 #define PTLIB_CLI_H
00038
00039 #include <ptlib.h>
00040 #include <ptlib/sockets.h>
00041
00042 #include <list>
00043
00044
00056 class PCLI : public PObject
00057 {
00058 PCLASSINFO(PCLI, PObject);
00059 public:
00060 class Context;
00061
00064 class Context : public PIndirectChannel
00065 {
00066 public:
00071 Context(
00072 PCLI & cli
00073 );
00074
00078 virtual ~Context();
00080
00097 virtual PBoolean Write(
00098 const void * buf,
00099 PINDEX len
00100 );
00102
00107 bool Start();
00108
00112 void Stop();
00113
00119 virtual void OnStart();
00120
00126 virtual void OnStop();
00127
00130 virtual bool WritePrompt();
00131
00135 virtual bool ReadAndProcessInput();
00136
00140 virtual bool ProcessInput(int ch);
00141
00148 virtual void OnCompletedLine();
00150
00155 PCLI & GetCLI() const { return m_cli; }
00156
00159 bool IsProcessingCommand() const { return m_state == e_ProcessingCommand; }
00161
00162 protected:
00163 PDECLARE_NOTIFIER(PThread, Context, ThreadMain);
00164
00165 PCLI & m_cli;
00166 PString m_commandLine;
00167 bool m_ignoreNextEOL;
00168 PStringList m_commandHistory;
00169 PThread * m_thread;
00170
00171 enum State {
00172 e_Username,
00173 e_Password,
00174 e_CommandEntry,
00175 e_ProcessingCommand
00176 } m_state;
00177 PString m_enteredUsername;
00178 };
00179
00182 class Arguments : public PArgList
00183 {
00184 public:
00187 Arguments(
00188 Context & context,
00189 const PString & rawLine
00190 );
00192
00197 Context & WriteUsage();
00198
00201 Context & WriteError(
00202 const PString & error = PString::Empty()
00203 );
00205
00210 Context & GetContext() const { return m_context; }
00212
00213 protected:
00214 Context & m_context;
00215 PString m_command;
00216 PString m_usage;
00217
00218 friend class PCLI;
00219 };
00220
00221
00226 PCLI(
00227 const char * prompt = NULL
00228 );
00229
00233 virtual ~PCLI();
00235
00246 virtual bool Start(
00247 bool runInBackground = true
00248 );
00249
00254 virtual void Stop();
00255
00258 bool StartContext(
00259 PChannel * channel,
00260 bool autoDelete = true,
00261 bool runInBackground = true
00262 );
00263 bool StartContext(
00264 PChannel * readChannel,
00265 PChannel * writeChannel,
00266 bool autoDeleteRead = true,
00267 bool autoDeleteWrite = true,
00268 bool runInBackground = true
00269 );
00270
00274 virtual Context * CreateContext();
00275
00279 virtual Context * AddContext(
00280 Context * context = NULL
00281 );
00282
00286 virtual void RemoveContext(
00287 Context * context
00288 );
00289
00292 virtual void GarbageCollection();
00293
00301 virtual void OnReceivedLine(
00302 Arguments & line
00303 );
00304
00317 virtual bool OnLogIn(
00318 const PString & username,
00319 const PString & password
00320 );
00321
00324 void Broadcast(
00325 const PString & message
00326 ) const;
00327
00338 bool SetCommand(
00339 const char * command,
00340 const PNotifier & notifier,
00341 const char * help = NULL,
00342 const char * usage = NULL
00343 );
00344
00347 void ShowHelp(
00348 Context & context
00349 );
00351
00357 const PString & GetNewLine() const { return m_newLine; }
00358
00362 void SetNewLine(const PString & newLine) { m_newLine = newLine; }
00363
00367 bool GetRequireEcho() const { return m_requireEcho; }
00368
00372 void SetRequireEcho(bool requireEcho) { m_requireEcho = requireEcho; }
00373
00377 const PString & GetEditCharacters() const { return m_editCharacters; }
00378
00382 void SetEditCharacters(const PString & editCharacters) { m_editCharacters = editCharacters; }
00383
00387 const PString & GetPrompt() const { return m_prompt; }
00388
00392 void SetPrompt(const PString & prompt) { m_prompt = prompt; }
00393
00397 const PString & GetUsernamePrompt() const { return m_usernamePrompt; }
00398
00402 void SetUsernamePrompt(const PString & prompt) { m_usernamePrompt = prompt; }
00403
00407 const PString & GetPasswordPrompt() const { return m_passwordPrompt; }
00408
00412 void SetPasswordPrompt(const PString & prompt) { m_passwordPrompt = prompt; }
00413
00417 const PString & GetUsername() const { return m_username; }
00418
00422 void SetUsername(const PString & username) { m_username = username; }
00423
00427 const PString & GetPassword() const { return m_password; }
00428
00432 void SetPassword(const PString & password) { m_password = password; }
00433
00437 const PCaselessString & GetExitCommand() const { return m_exitCommand; }
00438
00442 void SetExitCommand(const PCaselessString & exitCommand) { m_exitCommand = exitCommand; }
00443
00447 const PCaselessString & GetHelpCommand() const { return m_helpCommand; }
00448
00452 void SetHelpCommand(const PCaselessString & helpCommand) { m_helpCommand = helpCommand; }
00453
00458 const PString & GetHelpOnHelp() const { return m_helpOnHelp; }
00459
00464 void SetHelpOnHelp(const PCaselessString & helpOnHelp) { m_helpOnHelp = helpOnHelp; }
00465
00469 const PCaselessString & GetRepeatCommand() const { return m_repeatCommand; }
00470
00474 void SetRepeatCommand(const PCaselessString & repeatCommand) { m_repeatCommand = repeatCommand; }
00475
00479 const PCaselessString & GetHistoryCommand() const { return m_historyCommand; }
00480
00484 void SetHistoryCommand(const PCaselessString & historyCommand) { m_historyCommand = historyCommand; }
00485
00489 const PString & GetNoHistoryError() const { return m_noHistoryError; }
00490
00494 void SetNoHistoryError(const PString & noHistoryError) { m_noHistoryError = noHistoryError; }
00495
00499 const PString & GetCommandUsagePrefix() const { return m_commandUsagePrefix; }
00500
00504 void SetCommandUsagePrefix(const PString & commandUsagePrefix) { m_commandUsagePrefix = commandUsagePrefix; }
00505
00509 const PString & GetCommandErrorPrefix() const { return m_commandErrorPrefix; }
00510
00514 void SetCommandErrorPrefix(const PString & commandErrorPrefix) { m_commandErrorPrefix = commandErrorPrefix; }
00515
00519 const PString & GetUnknownCommandError() const { return m_unknownCommandError; }
00520
00524 void SetUnknownCommandError(const PString & unknownCommandError) { m_unknownCommandError = unknownCommandError; }
00526
00527 protected:
00528 PString m_newLine;
00529 bool m_requireEcho;
00530 PString m_editCharacters;
00531 PString m_prompt;
00532 PString m_usernamePrompt;
00533 PString m_passwordPrompt;
00534 PString m_username;
00535 PString m_password;
00536 PCaselessString m_exitCommand;
00537 PCaselessString m_helpCommand;
00538 PString m_helpOnHelp;
00539 PCaselessString m_repeatCommand;
00540 PCaselessString m_historyCommand;
00541 PString m_noHistoryError;
00542 PString m_commandUsagePrefix;
00543 PString m_commandErrorPrefix;
00544 PString m_unknownCommandError;
00545
00546 struct InternalCommand {
00547 PNotifier m_notifier;
00548 PString m_help;
00549 PString m_usage;
00550 };
00551 typedef std::map<PString, InternalCommand> CommandMap_t;
00552 CommandMap_t m_commands;
00553
00554 typedef std::list<Context *> ContextList_t;
00555 ContextList_t m_contextList;
00556 PMutex m_contextMutex;
00557 };
00558
00559
00562 class PCLIStandard : public PCLI
00563 {
00564 public:
00569 PCLIStandard(
00570 const char * prompt = NULL
00571 );
00573
00580 virtual bool Start(
00581 bool runInBackground = true
00582 );
00584 };
00585
00586
00591 class PCLISocket : public PCLI
00592 {
00593 public:
00596 PCLISocket(
00597 WORD port = 0,
00598 const char * prompt = NULL,
00599 bool singleThreadForAll = false
00600 );
00601 ~PCLISocket();
00603
00610 virtual bool Start(
00611 bool runInBackground = true
00612 );
00613
00621 virtual void Stop();
00622
00626 virtual Context * AddContext(
00627 Context * context = NULL
00628 );
00629
00633 virtual void RemoveContext(
00634 Context * context
00635 );
00637
00642 bool Listen(
00643 WORD port = 0
00644 );
00645
00648 WORD GetPort() const { return m_listenSocket.GetPort(); }
00650
00651 protected:
00652 PDECLARE_NOTIFIER(PThread, PCLISocket, ThreadMain);
00653 bool HandleSingleThreadForAll();
00654 bool HandleIncoming();
00655 virtual PTCPSocket * CreateSocket();
00656
00657 bool m_singleThreadForAll;
00658
00659 PTCPSocket m_listenSocket;
00660 PThread * m_thread;
00661
00662 typedef std::map<PSocket *, Context *> ContextMap_t;
00663 ContextMap_t m_contextBySocket;
00664 };
00665
00666
00671 class PCLITelnet : public PCLISocket
00672 {
00673 public:
00676 PCLITelnet(
00677 WORD port = 0,
00678 const char * prompt = NULL,
00679 bool singleThreadForAll = false
00680 );
00682
00683 protected:
00684 virtual PTCPSocket * CreateSocket();
00685 };
00686
00687
00688 #endif // PTLIB_CLI_H
00689
00690
00691