# cli.h

Go to the documentation of this file.

    00001 /*
    00002  * cli.h
    00003  *
    00004  * Command line interpreter
    00005  *
    00006  * Copyright (C) 2006-2008 Post Increment
    00007  *
    00008  * The contents of this file are subject to the Mozilla Public License
    00009  * Version 1.0 (the "License"); you may not use this file except in
    00010  * compliance with the License. You may obtain a copy of the License at
    00011  * http://www.mozilla.org/MPL/
    00012  *
    00013  * Software distributed under the License is distributed on an "AS IS"
    00014  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    00015  * the License for the specific language governing rights and limitations
    00016  * under the License.
    00017  *
    00018  * The Original Code is WOpenMCU
    00019  *
    00020  * The Initial Developer of the Original Code is Post Increment
    00021  *
    00022  * Contributor(s): Craig Southeren (craigs@postincrement.com)
    00023  *                 Robert Jongbloed (robertj@voxlucida.com.au)
    00024  *
    00025  * Portions of this code were written by Post Increment (http://www.postincrement.com)
    00026  * with the assistance of funding from US Joint Forces Command Joint Concept Development &
    00027  * Experimentation (J9) http://www.jfcom.mil/about/abt_j9.htm
    00028  *
    00029  * Further assistance for enhancements from Imagicle spa
    00030  *
    00031  * $Revision: 24931 $
    00032  * $Author: csoutheren $
    00033  * $Date: 2010-12-07 20:01:15 -0600 (Tue, 07 Dec 2010) $
    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 // End Of File ///////////////////////////////////////////////////////////////