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 NAMESPACE_UCOMMON
00050 
00058 class __EXPORT shell : public mempager
00059 {
00060 private:
00061     char **_argv;
00062     unsigned _argc;
00063     char *_argv0;
00064     char *_exedir;
00065     LinkedObject *_syms;
00066 
00067     class __LOCAL args : public OrderedObject
00068     {
00069     public:
00070         char *item;
00071     };
00072 
00073     class __LOCAL syms : public LinkedObject
00074     {
00075     public:
00076         const char *name;
00077         const char *value;
00078     };
00079 
00085     void collapse(LinkedObject *first);
00086 
00090     void set0(char *argv0);
00091 
00092 public:
00096     typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE, NUMERIC_SET} errmsg_t;
00097 
00101     typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG, SECURITY_LOG} logmode_t;
00102 
00106     typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t;
00107 
00111     typedef enum {NO_NUMERIC, NUMERIC_PLUS, NUMERIC_DASH, NUMERIC_ALL} numeric_t;
00112 
00116     typedef enum {
00117         PROGRAM_CONFIG, SERVICE_CONFIG, USER_DEFAULTS, SERVICE_CONTROL,
00118         USER_HOME = USER_DEFAULTS + 3, SERVICE_DATA, SYSTEM_TEMP, USER_CACHE,
00119         SERVICE_CACHE, USER_DATA, USER_CONFIG, SYSTEM_CFG, SYSTEM_ETC,
00120         SYSTEM_VAR, SYSTEM_PREFIX, SYSTEM_SHARE, PROGRAM_PLUGINS,
00121         PROGRAM_TEMP} path_t;
00122 
00126     typedef bool (*logproc_t)(loglevel_t level, const char *text);
00127 
00131     typedef cpr_service_t   mainproc_t;
00132 
00136     typedef void (*exitproc_t)(void);
00137 
00138 #ifdef  _MSWINDOWS_
00139     typedef HANDLE pid_t;
00140 #else
00141 
00144     typedef int pid_t;
00145 #endif
00146 
00150     typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t;
00151 
00160     class __EXPORT pipeio
00161     {
00162     protected:
00163         friend class shell;
00164 
00168         pipeio();
00169 
00179         int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00180 
00185         int wait(void);
00186 
00192         int cancel(void);
00193 
00202         size_t read(void *address, size_t size);
00203 
00212         size_t write(const void *address, size_t size);
00213 
00214         pid_t pid;
00215         fd_t input, output; // input to and output from child process...
00216         int perror, presult;
00217     };
00218 
00225     class __EXPORT iobuf : public BufferProtocol, private pipeio
00226     {
00227     protected:
00228         friend class shell;
00229 
00230         int ioerror;
00231 
00232         virtual int _err(void) const;
00233         virtual void _clear(void);
00234 
00235         virtual size_t _push(const char *address, size_t size);
00236         virtual size_t _pull(char *address, size_t size);
00237 
00238     public:
00244         iobuf(size_t size = 0);
00245 
00256         iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00257 
00262         ~iobuf();
00263 
00272         void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00273 
00278         void close(void);
00279 
00284         void cancel(void);
00285     };
00286 
00290     typedef iobuf io_t;
00291 
00295     typedef pipeio *pipe_t;
00296 
00303     static const char *errmsg(errmsg_t id);
00304 
00311     static void errmsg(errmsg_t id, const char *text);
00312 
00319     class __EXPORT errormap
00320     {
00321     public:
00322         inline errormap(errmsg_t id, const char *text)
00323             {shell::errmsg(id, text);};
00324     };
00325 
00333     class __EXPORT Option : public OrderedObject
00334     {
00335     public:
00336         char short_option;
00337         const char *long_option;
00338         const char *uses_option;
00339         const char *help_string;
00340         bool trigger_option;
00341 
00349         Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL);
00350 
00351         virtual ~Option();
00352 
00353         static LinkedObject *first(void);
00354 
00359         void disable(void);
00360 
00366         virtual const char *assign(const char *value) = 0;
00367 
00368         static void reset(void);
00369     };
00370 
00378     class __EXPORT flagopt : public Option
00379     {
00380     private:
00381         unsigned counter;
00382         bool single;
00383 
00384         virtual const char *assign(const char *value);
00385 
00386     public:
00387         flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true);
00388 
00389         inline operator bool()
00390             {return counter > 0;};
00391 
00392         inline bool operator!()
00393             {return counter == 0;};
00394 
00395         inline operator unsigned()
00396             {return counter;};
00397 
00398         inline unsigned operator*()
00399             {return counter;};
00400 
00401         inline void set(unsigned value = 1)
00402             {counter = value;};
00403     };
00404 
00410     class __EXPORT groupopt : public Option
00411     {
00412     private:
00413         virtual const char *assign(const char *value);
00414 
00415     public:
00416         groupopt(const char *help);
00417     };
00418 
00425     class __EXPORT stringopt : public Option
00426     {
00427     private:
00428         bool used;
00429 
00430     protected:
00431         const char *text;
00432 
00433         virtual const char *assign(const char *value);
00434 
00435     public:
00436         stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL);
00437 
00438         inline void set(const char *string)
00439             {text = string;};
00440 
00441         inline operator bool()
00442             {return used;};
00443 
00444         inline bool operator!()
00445             {return !used;};
00446 
00447         inline operator const char *()
00448             {return text;};
00449 
00450         inline const char *operator*()
00451             {return text;};
00452     };
00453 
00460     class __EXPORT charopt : public Option
00461     {
00462     private:
00463         bool used;
00464 
00465     protected:
00466         char code;
00467 
00468         virtual const char *assign(const char *value);
00469 
00470     public:
00471         charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' ');
00472 
00473         inline void set(char value)
00474             {code = value;};
00475 
00476         inline operator bool()
00477             {return used;};
00478 
00479         inline bool operator!()
00480             {return !used;};
00481 
00482         inline operator char()
00483             {return code;};
00484 
00485         inline char operator*()
00486             {return code;};
00487     };
00488 
00495     class __EXPORT numericopt : public Option
00496     {
00497     private:
00498         bool used;
00499 
00500     protected:
00501         long number;
00502 
00503         virtual const char *assign(const char *value);
00504 
00505     public:
00506         numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
00507 
00508         inline void set(long value)
00509             {number = value;};
00510 
00511         inline operator bool()
00512             {return used;};
00513 
00514         inline bool operator!()
00515             {return !used;};
00516 
00517         inline operator long()
00518             {return number;};
00519 
00520         inline long operator*()
00521             {return number;};
00522     };
00523 
00532     class __EXPORT counteropt : public Option
00533     {
00534     private:
00535         bool used;
00536 
00537     protected:
00538         long number;
00539 
00540         virtual const char *assign(const char *value);
00541 
00542     public:
00543         counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
00544 
00545         inline void set(long value)
00546             {number = value;};
00547 
00548         inline operator bool()
00549             {return used;};
00550 
00551         inline bool operator!()
00552             {return !used;};
00553 
00554         inline operator long()
00555             {return number;};
00556 
00557         inline long operator*()
00558             {return number;};
00559     };
00560 
00568     shell(const char *string, size_t pagesize = 0);
00569 
00578     shell(int argc, char **argv, size_t pagesize = 0);
00579 
00584     shell(size_t pagesize = 0);
00585 
00586     static void setNumeric(numeric_t);
00587 
00588     static long getNumeric(void);
00589 
00593     static void help(void);
00594 
00602     static int system(const char *command, const char **env = NULL);
00603 
00610     static int systemf(const char *format, ...) __PRINTF(1,2);
00611 
00616     static void relocate(const char *argv0);
00617 
00624     static String path(path_t id);
00625 
00630     static String userid(void);
00631 
00638     static String path(path_t id, const char *directory);
00639 
00645     static String path(String& prefix, const char *directory);
00646 
00658     static void bind(const char *name);
00659 
00669     static void rebind(const char *name = NULL);
00670 
00676     char **parse(const char *string);
00677 
00686     void parse(int argc, char **argv);
00687 
00695     const char *getenv(const char *name, const char *value = NULL);
00696 
00703     const char *getsym(const char *name, const char *value = NULL);
00704 
00710     void setsym(const char *name, const char *value);
00711 
00717     bool issym(const char *name);
00718 
00724     char *getargv0(char **argv);
00725 
00733     char **getargv(char **argv);
00734 
00741     void restart(char *argv0, char **argv, char **list);
00742 
00749     inline static char **parse(shell &args, const char *string)
00750         {return args.parse(string);}
00751 
00755     inline const char *argv0() const
00756         {return _argv0;}
00757 
00761     inline const char *execdir() const
00762         {return _exedir;}
00763 
00768     static void error(const char *format, ...) __PRINTF(1, 2);
00769 
00775     static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3);
00776 
00777 
00783     static inline int condition(bool test, int exitcode)
00784         { return (test) ? exitcode : 0;};
00785 
00791     static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3);
00792 
00798     static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
00799 
00805     static void security(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
00806 
00814     static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL);
00815 
00820     static size_t printf(const char *format, ...) __PRINTF(1, 2);
00821 
00822     static size_t readln(char *address, size_t size);
00823 
00824     static size_t writes(const char *string);
00825 
00826     static size_t read(String& string);
00827 
00828     inline static size_t write(String& string)
00829         {return writes(string.c_str());};
00830 
00837     static size_t printf(pipe_t pipe, const char *format, ...) __PRINTF(2, 3);
00838 
00846     static size_t readln(pipe_t pipe, char *buffer, size_t size);
00847 
00848     static size_t read(pipe_t pipe, String& string);
00849 
00850     static size_t writes(pipe_t pipe, const char *string);
00851 
00852     inline static size_t write(pipe_t pipe, String& string)
00853         {return writes(pipe, string.c_str());};
00854 
00860     inline unsigned argc(void) const
00861         {return _argc;};
00862 
00869     inline char **argv(void) const
00870         {return _argv;};
00871 
00877     inline const char *operator[](unsigned offset)
00878         {return _argv[offset];};
00879 
00880     static void exiting(exitproc_t);
00881 
00885     void detach(mainproc_t mainentry = (mainproc_t)NULL);
00886 
00890     void restart(void);
00891 
00903     static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
00904 
00916     static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00917 
00926     static void priority(int pri = 1);
00927 
00937     static int  detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
00938 
00944     static int wait(shell::pid_t pid);
00945 
00951     static int cancel(shell::pid_t pid);
00952 
00959     static int wait(shell::pipe_t pointer);
00960 
00966     static int cancel(shell::pipe_t pointer);
00967 
00972     inline unsigned operator()(void)
00973         {return _argc;};
00974 
00987     static const char *text(const char *string);
00988 
00998     static const char *texts(const char *singular, const char *plural, unsigned long count);
00999 
01005     static unsigned count(char **argv);
01006 
01007 #ifdef  _MSWINDOWS_
01008 
01009     static inline fd_t input(void)
01010         {return GetStdHandle(STD_INPUT_HANDLE);};
01011 
01012     static inline fd_t output(void)
01013         {return GetStdHandle(STD_OUTPUT_HANDLE);};
01014 
01015     static inline fd_t error(void)
01016         {return GetStdHandle(STD_ERROR_HANDLE);};
01017 
01018 #else
01019     static inline fd_t input(void)
01020         {return 0;};
01021 
01022     static inline fd_t output(void)
01023         {return 1;};
01024 
01025     static inline fd_t error(void)
01026         {return 2;};
01027 #endif
01028 
01029     static int inkey(const char *prompt = NULL);
01030 
01031     static char *getpass(const char *prompt, char *buffer, size_t size);
01032 
01033     static char *getline(const char *prompt, char *buffer, size_t size);
01034 
01035 };
01036 
01040 typedef shell shell_t;
01041 
01045 #undef  _TEXT
01046 #undef  _STR
01047 
01055 inline  const char *_TEXT(const char *s)
01056     {return shell::text(s);}
01057 
01058 inline const char *_STR(String& s)
01059     {return *s;}
01060 
01061 END_NAMESPACE
01062 
01063 #endif