PTLib  Version 2.12.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cli.h
Go to the documentation of this file.
1 /*
2  * cli.h
3  *
4  * Command line interpreter
5  *
6  * Copyright (C) 2006-2008 Post Increment
7  *
8  * The contents of this file are subject to the Mozilla Public License
9  * Version 1.0 (the "License"); you may not use this file except in
10  * compliance with the License. You may obtain a copy of the License at
11  * http://www.mozilla.org/MPL/
12  *
13  * Software distributed under the License is distributed on an "AS IS"
14  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15  * the License for the specific language governing rights and limitations
16  * under the License.
17  *
18  * The Original Code is WOpenMCU
19  *
20  * The Initial Developer of the Original Code is Post Increment
21  *
22  * Contributor(s): Craig Southeren (craigs@postincrement.com)
23  * Robert Jongbloed (robertj@voxlucida.com.au)
24  *
25  * Portions of this code were written by Post Increment (http://www.postincrement.com)
26  * with the assistance of funding from US Joint Forces Command Joint Concept Development &
27  * Experimentation (J9) http://www.jfcom.mil/about/abt_j9.htm
28  *
29  * Further assistance for enhancements from Imagicle spa
30  *
31  * $Revision: 28621 $
32  * $Author: rjongbloed $
33  * $Date: 2012-12-03 13:33:10 +1100 (Mon, 03 Dec 2012) $
34  */
35 
36 #ifndef PTLIB_CLI_H
37 #define PTLIB_CLI_H
38 
39 #include <ptbuildopts.h>
40 
41 #if P_CLI
42 
43 #include <ptlib/sockets.h>
44 
45 #include <list>
46 
47 
59 class PCLI : public PObject
60 {
61  PCLASSINFO(PCLI, PObject);
62  public:
63  class Context;
64 
67  class Context : public PIndirectChannel
68  {
69  public:
74  Context(
75  PCLI & cli
76  );
77 
81  virtual ~Context();
83 
100  virtual PBoolean Write(
101  const void * buf,
102  PINDEX len
103  );
105 
110  bool Start();
111 
115  void Stop();
116 
121  bool Run();
122 
128  virtual void OnStart();
129 
135  virtual void OnStop();
136 
139  virtual bool WritePrompt();
140 
144  virtual bool ReadAndProcessInput();
145 
149  virtual bool ProcessInput(int ch);
150  virtual bool ProcessInput(const PString & line);
151 
158  virtual void OnCompletedLine();
160 
165  PCLI & GetCLI() const { return m_cli; }
166 
169  bool IsProcessingCommand() const { return m_state == e_ProcessingCommand; }
171 
172  protected:
173  PDECLARE_NOTIFIER(PThread, Context, ThreadMain);
174 
175  PCLI & m_cli;
176  PString m_commandLine;
177  bool m_ignoreNextEOL;
178  PStringList m_commandHistory;
179  PThread * m_thread;
180 
181  enum State {
182  e_Username,
183  e_Password,
184  e_CommandEntry,
185  e_ProcessingCommand
186  } m_state;
187  PString m_enteredUsername;
188  };
189 
192  class Arguments : public PArgList
193  {
194  public:
197  Arguments(
198  Context & context,
199  const PString & rawLine
200  );
202 
207  Context & WriteUsage();
208 
211  Context & WriteError(
212  const PString & error = PString::Empty()
213  );
215 
220  Context & GetContext() const { return m_context; }
222 
223  protected:
224  Context & m_context;
225  PString m_usage;
226 
227  friend class PCLI;
228  };
229 
230 
235  PCLI(
236  const char * prompt = NULL
237  );
238 
242  virtual ~PCLI();
244 
255  virtual bool Start(
256  bool runInBackground = true
257  );
258 
263  virtual void Stop();
264 
270  Context * StartContext(
271  PChannel * channel,
272  bool autoDelete = true,
273  bool runInBackground = true
274  ) { return StartContext(channel, channel, autoDelete, autoDelete, runInBackground); }
275  Context * StartContext(
276  PChannel * readChannel,
277  PChannel * writeChannel,
278  bool autoDeleteRead = true,
279  bool autoDeleteWrite = true,
280  bool runInBackground = true
281  );
282 
286  virtual Context * StartForeground();
287 
293  bool Run(
294  PChannel & channel
295  ) { return Run(&channel, &channel, false, false); }
296  bool Run(
297  PChannel * channel,
298  bool autoDelete = true
299  ) { return Run(channel, channel, autoDelete, autoDelete); }
300  bool Run(
301  PChannel * readChannel,
302  PChannel * writeChannel,
303  bool autoDeleteRead = true,
304  bool autoDeleteWrite = true
305  );
306 
312  bool RunContext(
313  Context * context
314  ) { return context != NULL && context->Run(); }
315 
319  virtual Context * CreateContext();
320 
324  virtual Context * AddContext(
325  Context * context = NULL
326  );
327 
331  virtual void RemoveContext(
332  Context * context
333  );
334 
337  virtual void GarbageCollection();
338 
346  virtual void OnReceivedLine(
347  Arguments & line
348  );
349 
362  virtual bool OnLogIn(
363  const PString & username,
364  const PString & password
365  );
366 
369  void Broadcast(
370  const PString & message
371  ) const;
372 
383  bool SetCommand(
384  const char * command,
385  const PNotifier & notifier,
386  const char * help = NULL,
387  const char * usage = NULL,
388  const char * argSpec = NULL
389  );
390 
393  void ShowHelp(
394  Context & context
395  );
397 
403  const PString & GetNewLine() const { return m_newLine; }
404 
408  void SetNewLine(const PString & newLine) { m_newLine = newLine; }
409 
413  bool GetRequireEcho() const { return m_requireEcho; }
414 
418  void SetRequireEcho(bool requireEcho) { m_requireEcho = requireEcho; }
419 
423  const PString & GetEditCharacters() const { return m_editCharacters; }
424 
428  void SetEditCharacters(const PString & editCharacters) { m_editCharacters = editCharacters; }
429 
433  const PString & GetPrompt() const { return m_prompt; }
434 
438  void SetPrompt(const PString & prompt) { m_prompt = prompt; }
439 
443  const PString & GetUsernamePrompt() const { return m_usernamePrompt; }
444 
448  void SetUsernamePrompt(const PString & prompt) { m_usernamePrompt = prompt; }
449 
453  const PString & GetPasswordPrompt() const { return m_passwordPrompt; }
454 
458  void SetPasswordPrompt(const PString & prompt) { m_passwordPrompt = prompt; }
459 
463  const PString & GetUsername() const { return m_username; }
464 
468  void SetUsername(const PString & username) { m_username = username; }
469 
473  const PString & GetPassword() const { return m_password; }
474 
478  void SetPassword(const PString & password) { m_password = password; }
479 
483  const PCaselessString & GetCommentCommand() const { return m_commentCommand; }
484 
488  void SetCommentCommand(const PCaselessString & commentCommand) { m_commentCommand = commentCommand; }
489 
493  const PCaselessString & GetExitCommand() const { return m_exitCommand; }
494 
498  void SetExitCommand(const PCaselessString & exitCommand) { m_exitCommand = exitCommand; }
499 
503  const PCaselessString & GetHelpCommand() const { return m_helpCommand; }
504 
508  void SetHelpCommand(const PCaselessString & helpCommand) { m_helpCommand = helpCommand; }
509 
514  const PString & GetHelpOnHelp() const { return m_helpOnHelp; }
515 
520  void SetHelpOnHelp(const PCaselessString & helpOnHelp) { m_helpOnHelp = helpOnHelp; }
521 
525  const PCaselessString & GetRepeatCommand() const { return m_repeatCommand; }
526 
530  void SetRepeatCommand(const PCaselessString & repeatCommand) { m_repeatCommand = repeatCommand; }
531 
535  const PCaselessString & GetHistoryCommand() const { return m_historyCommand; }
536 
540  void SetHistoryCommand(const PCaselessString & historyCommand) { m_historyCommand = historyCommand; }
541 
545  const PString & GetNoHistoryError() const { return m_noHistoryError; }
546 
550  void SetNoHistoryError(const PString & noHistoryError) { m_noHistoryError = noHistoryError; }
551 
555  const PString & GetCommandUsagePrefix() const { return m_commandUsagePrefix; }
556 
560  void SetCommandUsagePrefix(const PString & commandUsagePrefix) { m_commandUsagePrefix = commandUsagePrefix; }
561 
565  const PString & GetCommandErrorPrefix() const { return m_commandErrorPrefix; }
566 
570  void SetCommandErrorPrefix(const PString & commandErrorPrefix) { m_commandErrorPrefix = commandErrorPrefix; }
571 
575  const PString & GetUnknownCommandError() const { return m_unknownCommandError; }
576 
580  void SetUnknownCommandError(const PString & unknownCommandError) { m_unknownCommandError = unknownCommandError; }
582 
583 
584  protected:
585  PString m_newLine;
586  bool m_requireEcho;
587  PString m_editCharacters;
588  PString m_prompt;
589  PString m_usernamePrompt;
590  PString m_passwordPrompt;
591  PString m_username;
592  PString m_password;
593  PCaselessString m_commentCommand;
594  PCaselessString m_exitCommand;
595  PCaselessString m_helpCommand;
596  PString m_helpOnHelp;
597  PCaselessString m_repeatCommand;
598  PCaselessString m_historyCommand;
599  PString m_noHistoryError;
600  PString m_commandUsagePrefix;
601  PString m_commandErrorPrefix;
602  PString m_unknownCommandError;
603 
604  struct InternalCommand {
605  PNotifier m_notifier;
606  PString m_help;
607  PString m_usage;
608  PString m_argSpec;
609  };
610  typedef std::map<PString, InternalCommand> CommandMap_t;
611  CommandMap_t m_commands;
612 
613  typedef std::list<Context *> ContextList_t;
614  ContextList_t m_contextList;
615  PMutex m_contextMutex;
616 };
617 
618 
621 class PCLIStandard : public PCLI
622 {
623  public:
628  PCLIStandard(
629  const char * prompt = NULL
630  );
632 
638  virtual Context * StartForeground();
640 
646  bool RunScript(
647  PChannel & channel
648  ) { return RunScript(&channel, false); }
649  bool RunScript(
650  PChannel * channel,
651  bool autoDelete = true
652  );
654 };
655 
656 
661 class PCLISocket : public PCLI
662 {
663  public:
666  PCLISocket(
667  WORD port = 0,
668  const char * prompt = NULL,
669  bool singleThreadForAll = false
670  );
671  ~PCLISocket();
673 
680  virtual bool Start(
681  bool runInBackground = true
682  );
683 
691  virtual void Stop();
692 
696  virtual Context * AddContext(
697  Context * context = NULL
698  );
699 
703  virtual void RemoveContext(
704  Context * context
705  );
707 
712  bool Listen(
713  WORD port = 0
714  );
715 
718  WORD GetPort() const { return m_listenSocket.GetPort(); }
720 
721  protected:
722  PDECLARE_NOTIFIER(PThread, PCLISocket, ThreadMain);
723  bool HandleSingleThreadForAll();
724  bool HandleIncoming();
725  virtual PTCPSocket * CreateSocket();
726 
727  bool m_singleThreadForAll;
728 
729  PTCPSocket m_listenSocket;
730  PThread * m_thread;
731 
732  typedef std::map<PSocket *, Context *> ContextMap_t;
733  ContextMap_t m_contextBySocket;
734 };
735 
736 
737 #if P_TELNET
738 
742 class PCLITelnet : public PCLISocket
743 {
744  public:
747  PCLITelnet(
748  WORD port = 0,
749  const char * prompt = NULL,
750  bool singleThreadForAll = false
751  );
753 
754  protected:
755  virtual PTCPSocket * CreateSocket();
756 };
757 #endif // P_TELNET
758 
759 #endif // P_CLI
760 
761 #endif // PTLIB_CLI_H
762 
763 
764 // End Of File ///////////////////////////////////////////////////////////////