UCommon
ucommon/shell.h
Go to the documentation of this file.
00001 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
00002 //
00003 // This file is part of GNU uCommon C++.
00004 //
00005 // GNU uCommon C++ is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU Lesser General Public License as published
00007 // by the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // GNU uCommon C++ is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with GNU uCommon C++.  If not, see <http://www.gnu.org/licenses/>.
00017 
00028 #ifndef _UCOMMON_STRING_H_
00029 #include <ucommon/string.h>
00030 #endif
00031 
00032 #ifndef _UCOMMON_MEMORY_H_
00033 #include <ucommon/memory.h>
00034 #endif
00035 
00036 #ifndef _UCOMMON_BUFFER_H_
00037 #include <ucommon/buffer.h>
00038 #endif
00039 
00040 #ifndef _UCOMMON_SHELL_H_
00041 #define _UCOMMON_SHELL_H_
00042 
00043 #ifdef  _MSWINDOWS_
00044 #define INVALID_PID_VALUE   INVALID_HANDLE_VALUE
00045 #else
00046 #define INVALID_PID_VALUE   -1
00047 #endif
00048 
00049 #ifdef  ERR
00050 #undef  ERR
00051 #endif
00052 
00053 NAMESPACE_UCOMMON
00054 
00062 class __EXPORT shell : public mempager
00063 {
00064 private:
00065     char **_argv;
00066     unsigned _argc;
00067     char *_argv0;
00068     char *_exedir;
00069     LinkedObject *_syms;
00070 
00071     class __LOCAL args : public OrderedObject
00072     {
00073     public:
00074         char *item;
00075     };
00076 
00077     class __LOCAL syms : public LinkedObject
00078     {
00079     public:
00080         const char *name;
00081         const char *value;
00082     };
00083 
00089     void collapse(LinkedObject *first);
00090 
00094     void set0(char *argv0);
00095 
00096 public:
00100     typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE, NUMERIC_SET} errmsg_t;
00101 
00105     typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG, SECURITY_LOG} logmode_t;
00106 
00110     typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t;
00111 
00115     typedef enum {NO_NUMERIC, NUMERIC_PLUS, NUMERIC_DASH, NUMERIC_ALL} numeric_t;
00116 
00120     typedef enum {
00121         PROGRAM_CONFIG, SERVICE_CONFIG, USER_DEFAULTS, SERVICE_CONTROL,
00122         USER_HOME = USER_DEFAULTS + 3, SERVICE_DATA, SYSTEM_TEMP, USER_CACHE,
00123         SERVICE_CACHE, USER_DATA, USER_CONFIG, SYSTEM_CFG, SYSTEM_ETC,
00124         SYSTEM_VAR, SYSTEM_PREFIX, SYSTEM_SHARE, PROGRAM_PLUGINS,
00125         PROGRAM_TEMP} path_t;
00126 
00130     typedef bool (*logproc_t)(loglevel_t level, const char *text);
00131 
00135     typedef cpr_service_t   mainproc_t;
00136 
00140     typedef void (*exitproc_t)(void);
00141 
00142 #ifdef  _MSWINDOWS_
00143     typedef HANDLE pid_t;
00144 #else
00145 
00148     typedef int pid_t;
00149 #endif
00150 
00154     typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t;
00155 
00164     class __EXPORT pipeio
00165     {
00166     protected:
00167         friend class shell;
00168 
00172         pipeio();
00173 
00183         int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00184 
00189         int wait(void);
00190 
00196         int cancel(void);
00197 
00206         size_t read(void *address, size_t size);
00207 
00216         size_t write(const void *address, size_t size);
00217 
00218         pid_t pid;
00219         fd_t input, output; // input to and output from child process...
00220         int perror, presult;
00221     };
00222 
00229     class __EXPORT iobuf : public BufferProtocol, private pipeio
00230     {
00231     protected:
00232         friend class shell;
00233 
00234         int ioerror;
00235 
00236         virtual int _err(void) const;
00237         virtual void _clear(void);
00238 
00239         virtual size_t _push(const char *address, size_t size);
00240         virtual size_t _pull(char *address, size_t size);
00241 
00242     public:
00248         iobuf(size_t size = 0);
00249 
00260         iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00261 
00266         ~iobuf();
00267 
00276         void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00277 
00282         void close(void);
00283 
00288         void cancel(void);
00289     };
00290 
00294     typedef iobuf io_t;
00295 
00299     typedef pipeio *pipe_t;
00300 
00307     static const char *errmsg(errmsg_t id);
00308 
00315     static void errmsg(errmsg_t id, const char *text);
00316 
00323     class __EXPORT errormap
00324     {
00325     public:
00326         inline errormap(errmsg_t id, const char *text)
00327             {shell::errmsg(id, text);};
00328     };
00329 
00337     class __EXPORT Option : public OrderedObject
00338     {
00339     public:
00340         char short_option;
00341         const char *long_option;
00342         const char *uses_option;
00343         const char *help_string;
00344         bool trigger_option;
00345 
00353         Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL);
00354 
00355         virtual ~Option();
00356 
00357         static LinkedObject *first(void);
00358 
00363         void disable(void);
00364 
00370         virtual const char *assign(const char *value) = 0;
00371 
00372         static void reset(void);
00373     };
00374 
00382     class __EXPORT flagopt : public Option
00383     {
00384     private:
00385         unsigned counter;
00386         bool single;
00387 
00388         virtual const char *assign(const char *value);
00389 
00390     public:
00391         flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true);
00392 
00393         inline operator bool()
00394             {return counter > 0;};
00395 
00396         inline bool operator!()
00397             {return counter == 0;};
00398 
00399         inline operator unsigned()
00400             {return counter;};
00401 
00402         inline unsigned operator*()
00403             {return counter;};
00404 
00405         inline void set(unsigned value = 1)
00406             {counter = value;};
00407     };
00408 
00414     class __EXPORT groupopt : public Option
00415     {
00416     private:
00417         virtual const char *assign(const char *value);
00418 
00419     public:
00420         groupopt(const char *help);
00421     };
00422 
00429     class __EXPORT stringopt : public Option
00430     {
00431     private:
00432         bool used;
00433 
00434     protected:
00435         const char *text;
00436 
00437         virtual const char *assign(const char *value);
00438 
00439     public:
00440         stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL);
00441 
00442         inline void set(const char *string)
00443             {text = string;};
00444 
00445         inline operator bool()
00446             {return used;};
00447 
00448         inline bool operator!()
00449             {return !used;};
00450 
00451         inline operator const char *()
00452             {return text;};
00453 
00454         inline const char *operator*()
00455             {return text;};
00456     };
00457 
00464     class __EXPORT charopt : public Option
00465     {
00466     private:
00467         bool used;
00468 
00469     protected:
00470         char code;
00471 
00472         virtual const char *assign(const char *value);
00473 
00474     public:
00475         charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' ');
00476 
00477         inline void set(char value)
00478             {code = value;};
00479 
00480         inline operator bool()
00481             {return used;};
00482 
00483         inline bool operator!()
00484             {return !used;};
00485 
00486         inline operator char()
00487             {return code;};
00488 
00489         inline char operator*()
00490             {return code;};
00491     };
00492 
00499     class __EXPORT numericopt : public Option
00500     {
00501     private:
00502         bool used;
00503 
00504     protected:
00505         long number;
00506 
00507         virtual const char *assign(const char *value);
00508 
00509     public:
00510         numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
00511 
00512         inline void set(long value)
00513             {number = value;};
00514 
00515         inline operator bool()
00516             {return used;};
00517 
00518         inline bool operator!()
00519             {return !used;};
00520 
00521         inline operator long()
00522             {return number;};
00523 
00524         inline long operator*()
00525             {return number;};
00526     };
00527 
00536     class __EXPORT counteropt : public Option
00537     {
00538     private:
00539         bool used;
00540 
00541     protected:
00542         long number;
00543 
00544         virtual const char *assign(const char *value);
00545 
00546     public:
00547         counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
00548 
00549         inline void set(long value)
00550             {number = value;};
00551 
00552         inline operator bool()
00553             {return used;};
00554 
00555         inline bool operator!()
00556             {return !used;};
00557 
00558         inline operator long()
00559             {return number;};
00560 
00561         inline long operator*()
00562             {return number;};
00563     };
00564 
00572     shell(const char *string, size_t pagesize = 0);
00573 
00582     shell(int argc, char **argv, size_t pagesize = 0);
00583 
00588     shell(size_t pagesize = 0);
00589 
00590     static void setNumeric(numeric_t);
00591 
00592     static long getNumeric(void);
00593 
00597     static void help(void);
00598 
00606     static int system(const char *command, const char **env = NULL);
00607 
00614     static int systemf(const char *format, ...) __PRINTF(1,2);
00615 
00620     static void relocate(const char *argv0);
00621 
00628     static String path(path_t id);
00629 
00634     static String userid(void);
00635 
00642     static String path(path_t id, const char *directory);
00643 
00649     static String path(String& prefix, const char *directory);
00650 
00662     static void bind(const char *name);
00663 
00673     static void rebind(const char *name = NULL);
00674 
00680     char **parse(const char *string);
00681 
00690     void parse(int argc, char **argv);
00691 
00699     const char *getenv(const char *name, const char *value = NULL);
00700 
00707     const char *getsym(const char *name, const char *value = NULL);
00708 
00714     void setsym(const char *name, const char *value);
00715 
00721     bool issym(const char *name);
00722 
00728     char *getargv0(char **argv);
00729 
00737     char **getargv(char **argv);
00738 
00745     void restart(char *argv0, char **argv, char **list);
00746 
00753     inline static char **parse(shell &args, const char *string)
00754         {return args.parse(string);}
00755 
00759     inline const char *argv0() const
00760         {return _argv0;}
00761 
00765     inline const char *execdir() const
00766         {return _exedir;}
00767 
00772     static void error(const char *format, ...) __PRINTF(1, 2);
00773 
00779     static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3);
00780 
00781 
00787     static inline int condition(bool test, int exitcode)
00788         { return (test) ? exitcode : 0;};
00789 
00795     static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3);
00796 
00802     static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
00803 
00809     static void security(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
00810 
00818     static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL);
00819 
00824     static size_t printf(const char *format, ...) __PRINTF(1, 2);
00825 
00826     static size_t readln(char *address, size_t size);
00827 
00828     static size_t writes(const char *string);
00829 
00830     static size_t read(String& string);
00831 
00832     inline static size_t write(String& string)
00833         {return writes(string.c_str());};
00834 
00841     static size_t printf(pipe_t pipe, const char *format, ...) __PRINTF(2, 3);
00842 
00850     static size_t readln(pipe_t pipe, char *buffer, size_t size);
00851 
00852     static size_t read(pipe_t pipe, String& string);
00853 
00854     static size_t writes(pipe_t pipe, const char *string);
00855 
00856     inline static size_t write(pipe_t pipe, String& string)
00857         {return writes(pipe, string.c_str());};
00858 
00864     inline unsigned argc(void) const
00865         {return _argc;};
00866 
00873     inline char **argv(void) const
00874         {return _argv;};
00875 
00881     inline const char *operator[](unsigned offset)
00882         {return _argv[offset];};
00883 
00884     static void exiting(exitproc_t);
00885 
00889     void detach(mainproc_t mainentry = (mainproc_t)NULL);
00890 
00894     void restart(void);
00895 
00907     static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
00908 
00920     static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00921 
00930     static void priority(int pri = 1);
00931 
00941     static int  detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
00942 
00948     static int wait(shell::pid_t pid);
00949 
00955     static int cancel(shell::pid_t pid);
00956 
00963     static int wait(shell::pipe_t pointer);
00964 
00970     static int cancel(shell::pipe_t pointer);
00971 
00976     inline unsigned operator()(void)
00977         {return _argc;};
00978 
00991     static const char *text(const char *string);
00992 
01002     static const char *texts(const char *singular, const char *plural, unsigned long count);
01003 
01009     static unsigned count(char **argv);
01010 
01011 #ifdef  _MSWINDOWS_
01012 
01013     static inline fd_t input(void)
01014         {return GetStdHandle(STD_INPUT_HANDLE);};
01015 
01016     static inline fd_t output(void)
01017         {return GetStdHandle(STD_OUTPUT_HANDLE);};
01018 
01019     static inline fd_t error(void)
01020         {return GetStdHandle(STD_ERROR_HANDLE);};
01021 
01022 #else
01023     static inline fd_t input(void)
01024         {return 0;};
01025 
01026     static inline fd_t output(void)
01027         {return 1;};
01028 
01029     static inline fd_t error(void)
01030         {return 2;};
01031 #endif
01032 
01033     static int inkey(const char *prompt = NULL);
01034 
01035     static char *getpass(const char *prompt, char *buffer, size_t size);
01036 
01037     static char *getline(const char *prompt, char *buffer, size_t size);
01038 
01039 };
01040 
01044 typedef shell shell_t;
01045 
01049 #undef  _TEXT
01050 #undef  _STR
01051 
01059 inline  const char *_TEXT(const char *s)
01060     {return shell::text(s);}
01061 
01062 inline const char *_STR(String& s)
01063     {return *s;}
01064 
01065 END_NAMESPACE
01066 
01067 #endif