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 virtual bool ProcessInput(const PString & line);
00142
00149 virtual void OnCompletedLine();
00151
00156 PCLI & GetCLI() const { return m_cli; }
00157
00160 bool IsProcessingCommand() const { return m_state == e_ProcessingCommand; }
00162
00163 protected:
00164 PDECLARE_NOTIFIER(PThread, Context, ThreadMain);
00165
00166 PCLI & m_cli;
00167 PString m_commandLine;
00168 bool m_ignoreNextEOL;
00169 PStringList m_commandHistory;
00170 PThread * m_thread;
00171
00172 enum State {
00173 e_Username,
00174 e_Password,
00175 e_CommandEntry,
00176 e_ProcessingCommand
00177 } m_state;
00178 PString m_enteredUsername;
00179 };
00180
00183 class Arguments : public PArgList
00184 {
00185 public:
00188 Arguments(
00189 Context & context,
00190 const PString & rawLine
00191 );
00193
00198 Context & WriteUsage();
00199
00202 Context & WriteError(
00203 const PString & error = PString::Empty()
00204 );
00206
00211 Context & GetContext() const { return m_context; }
00213
00214 protected:
00215 Context & m_context;
00216 PString m_command;
00217 PString m_usage;
00218
00219 friend class PCLI;
00220 };
00221
00222
00227 PCLI(
00228 const char * prompt = NULL
00229 );
00230
00234 virtual ~PCLI();
00236
00247 virtual bool Start(
00248 bool runInBackground = true
00249 );
00250
00255 virtual void Stop();
00256
00259 bool StartContext(
00260 PChannel * channel,
00261 bool autoDelete = true,
00262 bool runInBackground = true
00263 );
00264 bool StartContext(
00265 PChannel * readChannel,
00266 PChannel * writeChannel,
00267 bool autoDeleteRead = true,
00268 bool autoDeleteWrite = true,
00269 bool runInBackground = true
00270 );
00271
00275 virtual Context * CreateContext();
00276
00280 virtual Context * AddContext(
00281 Context * context = NULL
00282 );
00283
00287 virtual void RemoveContext(
00288 Context * context
00289 );
00290
00293 virtual void GarbageCollection();
00294
00302 virtual void OnReceivedLine(
00303 Arguments & line
00304 );
00305
00318 virtual bool OnLogIn(
00319 const PString & username,
00320 const PString & password
00321 );
00322
00325 void Broadcast(
00326 const PString & message
00327 ) const;
00328
00339 bool SetCommand(
00340 const char * command,
00341 const PNotifier & notifier,
00342 const char * help = NULL,
00343 const char * usage = NULL
00344 );
00345
00348 void ShowHelp(
00349 Context & context
00350 );
00352
00358 const PString & GetNewLine() const { return m_newLine; }
00359
00363 void SetNewLine(const PString & newLine) { m_newLine = newLine; }
00364
00368 bool GetRequireEcho() const { return m_requireEcho; }
00369
00373 void SetRequireEcho(bool requireEcho) { m_requireEcho = requireEcho; }
00374
00378 const PString & GetEditCharacters() const { return m_editCharacters; }
00379
00383 void SetEditCharacters(const PString & editCharacters) { m_editCharacters = editCharacters; }
00384
00388 const PString & GetPrompt() const { return m_prompt; }
00389
00393 void SetPrompt(const PString & prompt) { m_prompt = prompt; }
00394
00398 const PString & GetUsernamePrompt() const { return m_usernamePrompt; }
00399
00403 void SetUsernamePrompt(const PString & prompt) { m_usernamePrompt = prompt; }
00404
00408 const PString & GetPasswordPrompt() const { return m_passwordPrompt; }
00409
00413 void SetPasswordPrompt(const PString & prompt) { m_passwordPrompt = prompt; }
00414
00418 const PString & GetUsername() const { return m_username; }
00419
00423 void SetUsername(const PString & username) { m_username = username; }
00424
00428 const PString & GetPassword() const { return m_password; }
00429
00433 void SetPassword(const PString & password) { m_password = password; }
00434
00438 const PCaselessString & GetExitCommand() const { return m_exitCommand; }
00439
00443 void SetExitCommand(const PCaselessString & exitCommand) { m_exitCommand = exitCommand; }
00444
00448 const PCaselessString & GetHelpCommand() const { return m_helpCommand; }
00449
00453 void SetHelpCommand(const PCaselessString & helpCommand) { m_helpCommand = helpCommand; }
00454
00459 const PString & GetHelpOnHelp() const { return m_helpOnHelp; }
00460
00465 void SetHelpOnHelp(const PCaselessString & helpOnHelp) { m_helpOnHelp = helpOnHelp; }
00466
00470 const PCaselessString & GetRepeatCommand() const { return m_repeatCommand; }
00471
00475 void SetRepeatCommand(const PCaselessString & repeatCommand) { m_repeatCommand = repeatCommand; }
00476
00480 const PCaselessString & GetHistoryCommand() const { return m_historyCommand; }
00481
00485 void SetHistoryCommand(const PCaselessString & historyCommand) { m_historyCommand = historyCommand; }
00486
00490 const PString & GetNoHistoryError() const { return m_noHistoryError; }
00491
00495 void SetNoHistoryError(const PString & noHistoryError) { m_noHistoryError = noHistoryError; }
00496
00500 const PString & GetCommandUsagePrefix() const { return m_commandUsagePrefix; }
00501
00505 void SetCommandUsagePrefix(const PString & commandUsagePrefix) { m_commandUsagePrefix = commandUsagePrefix; }
00506
00510 const PString & GetCommandErrorPrefix() const { return m_commandErrorPrefix; }
00511
00515 void SetCommandErrorPrefix(const PString & commandErrorPrefix) { m_commandErrorPrefix = commandErrorPrefix; }
00516
00520 const PString & GetUnknownCommandError() const { return m_unknownCommandError; }
00521
00525 void SetUnknownCommandError(const PString & unknownCommandError) { m_unknownCommandError = unknownCommandError; }
00527
00530 virtual Context * StartForeground();
00531
00534 virtual bool RunContext(Context * context);
00535
00536
00537 protected:
00538 PString m_newLine;
00539 bool m_requireEcho;
00540 PString m_editCharacters;
00541 PString m_prompt;
00542 PString m_usernamePrompt;
00543 PString m_passwordPrompt;
00544 PString m_username;
00545 PString m_password;
00546 PCaselessString m_exitCommand;
00547 PCaselessString m_helpCommand;
00548 PString m_helpOnHelp;
00549 PCaselessString m_repeatCommand;
00550 PCaselessString m_historyCommand;
00551 PString m_noHistoryError;
00552 PString m_commandUsagePrefix;
00553 PString m_commandErrorPrefix;
00554 PString m_unknownCommandError;
00555
00556 struct InternalCommand {
00557 PNotifier m_notifier;
00558 PString m_help;
00559 PString m_usage;
00560 };
00561 typedef std::map<PString, InternalCommand> CommandMap_t;
00562 CommandMap_t m_commands;
00563
00564 typedef std::list<Context *> ContextList_t;
00565 ContextList_t m_contextList;
00566 PMutex m_contextMutex;
00567 };
00568
00569
00572 class PCLIStandard : public PCLI
00573 {
00574 public:
00579 PCLIStandard(
00580 const char * prompt = NULL
00581 );
00583
00590 virtual bool Start(
00591 bool runInBackground = true
00592 );
00594
00595 PCLI::Context * StartForeground();
00596 };
00597
00598
00603 class PCLISocket : public PCLI
00604 {
00605 public:
00608 PCLISocket(
00609 WORD port = 0,
00610 const char * prompt = NULL,
00611 bool singleThreadForAll = false
00612 );
00613 ~PCLISocket();
00615
00622 virtual bool Start(
00623 bool runInBackground = true
00624 );
00625
00633 virtual void Stop();
00634
00638 virtual Context * AddContext(
00639 Context * context = NULL
00640 );
00641
00645 virtual void RemoveContext(
00646 Context * context
00647 );
00649
00654 bool Listen(
00655 WORD port = 0
00656 );
00657
00660 WORD GetPort() const { return m_listenSocket.GetPort(); }
00662
00663 protected:
00664 PDECLARE_NOTIFIER(PThread, PCLISocket, ThreadMain);
00665 bool HandleSingleThreadForAll();
00666 bool HandleIncoming();
00667 virtual PTCPSocket * CreateSocket();
00668
00669 bool m_singleThreadForAll;
00670
00671 PTCPSocket m_listenSocket;
00672 PThread * m_thread;
00673
00674 typedef std::map<PSocket *, Context *> ContextMap_t;
00675 ContextMap_t m_contextBySocket;
00676 };
00677
00678
00683 class PCLITelnet : public PCLISocket
00684 {
00685 public:
00688 PCLITelnet(
00689 WORD port = 0,
00690 const char * prompt = NULL,
00691 bool singleThreadForAll = false
00692 );
00694
00695 protected:
00696 virtual PTCPSocket * CreateSocket();
00697 };
00698
00699
00700 #endif // PTLIB_CLI_H
00701
00702
00703