UCommon
shell.h
Go to the documentation of this file.
1 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU uCommon C++.
4 //
5 // GNU uCommon C++ is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU uCommon C++ is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17 
28 #ifndef _UCOMMON_STRING_H_
29 #include <ucommon/string.h>
30 #endif
31 
32 #ifndef _UCOMMON_MEMORY_H_
33 #include <ucommon/memory.h>
34 #endif
35 
36 #ifndef _UCOMMON_BUFFER_H_
37 #include <ucommon/buffer.h>
38 #endif
39 
40 #ifndef _UCOMMON_SHELL_H_
41 #define _UCOMMON_SHELL_H_
42 
43 #ifdef _MSWINDOWS_
44 #define INVALID_PID_VALUE INVALID_HANDLE_VALUE
45 #else
46 #define INVALID_PID_VALUE -1
47 #endif
48 
49 #ifdef ERR
50 #undef ERR
51 #endif
52 
53 NAMESPACE_UCOMMON
54 
62 class __EXPORT shell : public mempager
63 {
64 private:
65  char **_argv;
66  unsigned _argc;
67  char *_argv0;
68  char *_exedir;
69  LinkedObject *_syms;
70 
71  class __LOCAL args : public OrderedObject
72  {
73  public:
74  char *item;
75  };
76 
77  class __LOCAL syms : public LinkedObject
78  {
79  public:
80  const char *name;
81  const char *value;
82  };
83 
89  void collapse(LinkedObject *first);
90 
94  void set0(char *argv0);
95 
96 public:
100  typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE, NUMERIC_SET} errmsg_t;
101 
105  typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG, SECURITY_LOG} logmode_t;
106 
110  typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t;
111 
115  typedef enum {NO_NUMERIC, NUMERIC_PLUS, NUMERIC_DASH, NUMERIC_ALL} numeric_t;
116 
120  typedef enum {
121  PROGRAM_CONFIG, SERVICE_CONFIG, USER_DEFAULTS, SERVICE_CONTROL,
122  USER_HOME = USER_DEFAULTS + 3, SERVICE_DATA, SYSTEM_TEMP, USER_CACHE,
123  SERVICE_CACHE, USER_DATA, USER_CONFIG, SYSTEM_CFG, SYSTEM_ETC,
124  SYSTEM_VAR, SYSTEM_PREFIX, SYSTEM_SHARE, PROGRAM_PLUGINS,
125  PROGRAM_TEMP} path_t;
126 
130  typedef bool (*logproc_t)(loglevel_t level, const char *text);
131 
135  typedef cpr_service_t mainproc_t;
136 
140  typedef void (*exitproc_t)(void);
141 
142 #ifdef _MSWINDOWS_
143  typedef HANDLE pid_t;
144 #else
145 
148  typedef int pid_t;
149 #endif
150 
154  typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t;
155 
164  class __EXPORT pipeio
165  {
166  protected:
167  friend class shell;
168 
172  pipeio();
173 
183  int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
184 
189  int wait(void);
190 
196  int cancel(void);
197 
206  size_t read(void *address, size_t size);
207 
216  size_t write(const void *address, size_t size);
217 
218  pid_t pid;
219  fd_t input, output; // input to and output from child process...
220  int perror, presult;
221  };
222 
229  class __EXPORT iobuf : public BufferProtocol, private pipeio
230  {
231  protected:
232  friend class shell;
233 
234  int ioerror;
235 
236  virtual int _err(void) const;
237  virtual void _clear(void);
238 
239  virtual size_t _push(const char *address, size_t size);
240  virtual size_t _pull(char *address, size_t size);
241 
242  public:
248  iobuf(size_t size = 0);
249 
260  iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
261 
266  ~iobuf();
267 
276  void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
277 
282  void close(void);
283 
288  void cancel(void);
289  };
290 
294  typedef iobuf io_t;
295 
299  typedef pipeio *pipe_t;
300 
307  static const char *errmsg(errmsg_t id);
308 
315  static void errmsg(errmsg_t id, const char *text);
316 
323  class __EXPORT errormap
324  {
325  public:
326  inline errormap(errmsg_t id, const char *text)
327  {shell::errmsg(id, text);};
328  };
329 
337  class __EXPORT Option : public OrderedObject
338  {
339  public:
340  char short_option;
341  const char *long_option;
342  const char *uses_option;
343  const char *help_string;
344  bool trigger_option;
345 
353  Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL);
354 
355  virtual ~Option();
356 
357  static LinkedObject *first(void);
358 
363  void disable(void);
364 
370  virtual const char *assign(const char *value) = 0;
371 
372  static void reset(void);
373  };
374 
382  class __EXPORT flagopt : public Option
383  {
384  private:
385  unsigned counter;
386  bool single;
387 
388  virtual const char *assign(const char *value);
389 
390  public:
391  flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true);
392 
393  inline operator bool()
394  {return counter > 0;};
395 
396  inline bool operator!()
397  {return counter == 0;};
398 
399  inline operator unsigned()
400  {return counter;};
401 
402  inline unsigned operator*()
403  {return counter;};
404 
405  inline void set(unsigned value = 1)
406  {counter = value;};
407  };
408 
414  class __EXPORT groupopt : public Option
415  {
416  private:
417  virtual const char *assign(const char *value);
418 
419  public:
420  groupopt(const char *help);
421  };
422 
429  class __EXPORT stringopt : public Option
430  {
431  private:
432  bool used;
433 
434  protected:
435  const char *text;
436 
437  virtual const char *assign(const char *value);
438 
439  public:
440  stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL);
441 
442  inline void set(const char *string)
443  {text = string;};
444 
445  inline operator bool()
446  {return used;};
447 
448  inline bool operator!()
449  {return !used;};
450 
451  inline operator const char *()
452  {return text;};
453 
454  inline const char *operator*()
455  {return text;};
456  };
457 
464  class __EXPORT charopt : public Option
465  {
466  private:
467  bool used;
468 
469  protected:
470  char code;
471 
472  virtual const char *assign(const char *value);
473 
474  public:
475  charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' ');
476 
477  inline void set(char value)
478  {code = value;};
479 
480  inline operator bool()
481  {return used;};
482 
483  inline bool operator!()
484  {return !used;};
485 
486  inline operator char()
487  {return code;};
488 
489  inline char operator*()
490  {return code;};
491  };
492 
499  class __EXPORT numericopt : public Option
500  {
501  private:
502  bool used;
503 
504  protected:
505  long number;
506 
507  virtual const char *assign(const char *value);
508 
509  public:
510  numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
511 
512  inline void set(long value)
513  {number = value;};
514 
515  inline operator bool()
516  {return used;};
517 
518  inline bool operator!()
519  {return !used;};
520 
521  inline operator long()
522  {return number;};
523 
524  inline long operator*()
525  {return number;};
526  };
527 
536  class __EXPORT counteropt : public Option
537  {
538  private:
539  bool used;
540 
541  protected:
542  long number;
543 
544  virtual const char *assign(const char *value);
545 
546  public:
547  counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
548 
549  inline void set(long value)
550  {number = value;};
551 
552  inline operator bool()
553  {return used;};
554 
555  inline bool operator!()
556  {return !used;};
557 
558  inline operator long()
559  {return number;};
560 
561  inline long operator*()
562  {return number;};
563  };
564 
572  shell(const char *string, size_t pagesize = 0);
573 
582  shell(int argc, char **argv, size_t pagesize = 0);
583 
588  shell(size_t pagesize = 0);
589 
590  static void setNumeric(numeric_t);
591 
592  static long getNumeric(void);
593 
597  static void help(void);
598 
606  static int system(const char *command, const char **env = NULL);
607 
614  static int systemf(const char *format, ...) __PRINTF(1,2);
615 
620  static void relocate(const char *argv0);
621 
628  static String path(path_t id);
629 
634  static String userid(void);
635 
642  static String path(path_t id, const char *directory);
643 
649  static String path(String& prefix, const char *directory);
650 
662  static void bind(const char *name);
663 
673  static void rebind(const char *name = NULL);
674 
680  char **parse(const char *string);
681 
690  void parse(int argc, char **argv);
691 
699  const char *getenv(const char *name, const char *value = NULL);
700 
707  const char *getsym(const char *name, const char *value = NULL);
708 
714  void setsym(const char *name, const char *value);
715 
721  bool issym(const char *name);
722 
728  char *getargv0(char **argv);
729 
737  char **getargv(char **argv);
738 
745  void restart(char *argv0, char **argv, char **list);
746 
753  inline static char **parse(shell &args, const char *string)
754  {return args.parse(string);}
755 
759  inline const char *argv0() const
760  {return _argv0;}
761 
765  inline const char *execdir() const
766  {return _exedir;}
767 
772  static void error(const char *format, ...) __PRINTF(1, 2);
773 
779  static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3);
780 
781 
787  static inline int condition(bool test, int exitcode)
788  { return (test) ? exitcode : 0;};
789 
795  static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3);
796 
802  static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
803 
809  static void security(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
810 
818  static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL);
819 
824  static size_t printf(const char *format, ...) __PRINTF(1, 2);
825 
826  static size_t readln(char *address, size_t size);
827 
828  static size_t writes(const char *string);
829 
830  static size_t read(String& string);
831 
832  inline static size_t write(String& string)
833  {return writes(string.c_str());};
834 
841  static size_t printf(pipe_t pipe, const char *format, ...) __PRINTF(2, 3);
842 
850  static size_t readln(pipe_t pipe, char *buffer, size_t size);
851 
852  static size_t read(pipe_t pipe, String& string);
853 
854  static size_t writes(pipe_t pipe, const char *string);
855 
856  inline static size_t write(pipe_t pipe, String& string)
857  {return writes(pipe, string.c_str());};
858 
864  inline unsigned argc(void) const
865  {return _argc;};
866 
873  inline char **argv(void) const
874  {return _argv;};
875 
881  inline const char *operator[](unsigned offset)
882  {return _argv[offset];};
883 
884  static void exiting(exitproc_t);
885 
889  void detach(mainproc_t mainentry = (mainproc_t)NULL);
890 
894  void restart(void);
895 
907  static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
908 
920  static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
921 
930  static void priority(int pri = 1);
931 
941  static int detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
942 
947  static void release(int exit_code = 0);
948 
954  static int wait(shell::pid_t pid);
955 
961  static int cancel(shell::pid_t pid);
962 
969  static int wait(shell::pipe_t pointer);
970 
976  static int cancel(shell::pipe_t pointer);
977 
982  inline unsigned operator()(void)
983  {return _argc;};
984 
997  static const char *text(const char *string);
998 
1008  static const char *texts(const char *singular, const char *plural, unsigned long count);
1009 
1015  static unsigned count(char **argv);
1016 
1017 #ifdef _MSWINDOWS_
1018 
1019  static inline fd_t input(void)
1020  {return GetStdHandle(STD_INPUT_HANDLE);};
1021 
1022  static inline fd_t output(void)
1023  {return GetStdHandle(STD_OUTPUT_HANDLE);};
1024 
1025  static inline fd_t error(void)
1026  {return GetStdHandle(STD_ERROR_HANDLE);};
1027 
1028 #else
1029  static inline fd_t input(void)
1030  {return 0;};
1031 
1032  static inline fd_t output(void)
1033  {return 1;};
1034 
1035  static inline fd_t error(void)
1036  {return 2;};
1037 #endif
1038 
1039  static int inkey(const char *prompt = NULL);
1040 
1041  static char *getpass(const char *prompt, char *buffer, size_t size);
1042 
1043  static char *getline(const char *prompt, char *buffer, size_t size);
1044 
1045 };
1046 
1050 typedef shell shell_t;
1051 
1055 #undef _TEXT
1056 #undef _STR
1057 
1065 inline const char *_TEXT(const char *s)
1066  {return shell::text(s);}
1067 
1068 inline const char *_STR(String& s)
1069  {return *s;}
1070 
1071 END_NAMESPACE
1072 
1073 #endif