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     LinkedObject *_syms;
00065 
00066     static const char *domain;
00067 
00068     class __LOCAL args : public OrderedObject
00069     {
00070     public:
00071         char *item;
00072     };
00073 
00074     class __LOCAL syms : public LinkedObject
00075     {
00076     public:
00077         const char *name;
00078         const char *value;
00079     };      
00080     
00086     void collapse(LinkedObject *first);
00087 
00091     void set0(char *argv0);
00092 
00093 public:
00097     typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE} errmsg_t;
00098 
00102     typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG} logmode_t;
00103 
00107     typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t;
00108 
00112     typedef bool (*logproc_t)(loglevel_t level, const char *text);
00113 
00117     typedef void (*downproc_t)(bool reload);
00118 
00119 #ifdef  _MSWINDOWS_
00120     typedef HANDLE pid_t;
00121 #else
00122 
00125     typedef int pid_t;
00126 #endif
00127 
00131     typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t;
00132 
00141     class __EXPORT pipeio
00142     {
00143     protected:
00144         friend class shell;
00145 
00149         pipeio();
00150 
00160         int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00161         
00166         int wait(void);
00167 
00173         int cancel(void);
00174 
00183         size_t read(void *address, size_t size);
00184 
00193         size_t write(const void *address, size_t size);
00194             
00195         pid_t pid;
00196         fd_t input, output; // input to and output from child process...
00197         int perror, presult;
00198     };
00199 
00206     class __EXPORT iobuf : public BufferProtocol, private pipeio
00207     {
00208     protected:
00209         friend class shell;
00210 
00211         int ioerror;
00212 
00213         virtual int _err(void) const;
00214         virtual void _clear(void);
00215 
00216         virtual size_t _push(const char *address, size_t size);
00217         virtual size_t _pull(char *address, size_t size);
00218 
00219     public:
00225         iobuf(size_t size = 0);
00226 
00237         iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00238 
00243         ~iobuf();
00244 
00253         void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00254 
00259         void close(void);
00260 
00265         void cancel(void);
00266     };
00267 
00271     typedef iobuf io_t;
00272 
00276     typedef pipeio *pipe_t;
00277 
00284     static const char *errmsg(errmsg_t id);
00285 
00292     static void errmsg(errmsg_t id, const char *text);
00293 
00300     class __EXPORT errormap
00301     {
00302     public:
00303         inline errormap(errmsg_t id, const char *text)
00304             {shell::errmsg(id, text);};
00305     };  
00306 
00314     class __EXPORT Option : public OrderedObject
00315     {
00316     private:
00317         static OrderedIndex index;
00318 
00319     public:
00320         char short_option;
00321         const char *long_option;
00322         const char *uses_option;
00323         const char *help_string;
00324         bool trigger_option;
00325 
00333         Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL);
00334 
00335         virtual ~Option();
00336 
00337         inline static LinkedObject *first(void)
00338             {return index.begin();};
00339 
00344         void disable(void);
00345 
00351         virtual const char *assign(const char *value) = 0;
00352 
00353         inline static void reset(void)
00354             {index.reset();};
00355     };
00356 
00364     class __EXPORT flagopt : public Option
00365     {
00366     private:
00367         unsigned counter;
00368         bool single;
00369 
00370         virtual const char *assign(const char *value);
00371 
00372     public:
00373         flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true);
00374 
00375         inline operator bool()
00376             {return counter > 0;};
00377 
00378         inline bool operator!()
00379             {return counter == 0;};
00380 
00381         inline operator unsigned()
00382             {return counter;};
00383 
00384         inline unsigned operator*()
00385             {return counter;};
00386 
00387         inline void set(unsigned value = 1)
00388             {counter = value;};
00389     };
00390 
00396     class __EXPORT groupopt : public Option
00397     {
00398     private:
00399         virtual const char *assign(const char *value);
00400 
00401     public:
00402         groupopt(const char *help);
00403     };
00404 
00411     class __EXPORT stringopt : public Option
00412     {
00413     private:
00414         bool used;
00415 
00416     protected:
00417         const char *text;
00418 
00419         virtual const char *assign(const char *value);
00420 
00421     public:
00422         stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL);
00423 
00424         inline void set(const char *string)
00425             {text = string;};
00426 
00427         inline operator bool()
00428             {return used;};
00429 
00430         inline bool operator!()
00431             {return !used;};
00432 
00433         inline operator const char *()
00434             {return text;};
00435 
00436         inline const char *operator*()
00437             {return text;};
00438     };
00439 
00446     class __EXPORT charopt : public Option
00447     {
00448     private:
00449         bool used;
00450 
00451     protected:
00452         char code;
00453 
00454         virtual const char *assign(const char *value);
00455 
00456     public:
00457         charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' ');
00458 
00459         inline void set(char value)
00460             {code = value;};
00461 
00462         inline operator bool()
00463             {return used;};
00464 
00465         inline bool operator!()
00466             {return !used;};
00467 
00468         inline operator char()
00469             {return code;};
00470 
00471         inline char operator*()
00472             {return code;};
00473     };
00474 
00481     class __EXPORT numericopt : public Option
00482     {
00483     private:
00484         bool used;
00485 
00486     protected:
00487         long number;
00488 
00489         virtual const char *assign(const char *value);
00490 
00491     public:
00492         numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
00493 
00494         inline void set(long value)
00495             {number = value;};
00496 
00497         inline operator bool()
00498             {return used;};
00499 
00500         inline bool operator!()
00501             {return !used;};
00502 
00503         inline operator long()
00504             {return number;};
00505 
00506         inline long operator*()
00507             {return number;};
00508     };
00509 
00518     class __EXPORT counteropt : public Option
00519     {
00520     private:
00521         bool used;
00522 
00523     protected:
00524         long number;
00525 
00526         virtual const char *assign(const char *value);
00527 
00528     public:
00529         counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0);
00530 
00531         inline void set(long value)
00532             {number = value;};
00533 
00534         inline operator bool()
00535             {return used;};
00536 
00537         inline bool operator!()
00538             {return !used;};
00539 
00540         inline operator long()
00541             {return number;};
00542 
00543         inline long operator*()
00544             {return number;};
00545     };
00546 
00554     shell(const char *string, size_t pagesize = 0);
00555 
00564     shell(int argc, char **argv, size_t pagesize = 0);
00565 
00570     shell(size_t pagesize = 0);
00571 
00575     static void help(void);
00576 
00584     static int system(const char *command, const char **env = NULL);
00585 
00592     static int systemf(const char *format, ...) __PRINTF(1,2);
00593 
00605     static void bind(const char *name);
00606 
00616     static void rebind(const char *name = NULL);
00617 
00623     char **parse(const char *string);
00624 
00633     void parse(int argc, char **argv);
00634 
00642     const char *getenv(const char *name, const char *value = NULL);
00643 
00650     const char *getsym(const char *name, const char *value = NULL);
00651 
00657     void setsym(const char *name, const char *value);
00658 
00664     bool issym(const char *name);
00665 
00671     char *getargv0(char **argv);
00672 
00680     char **getargv(char **argv);
00681 
00688     void restart(char *argv0, char **argv, char **list);
00689 
00693     void up(void);
00694 
00701     inline static char **parse(shell &args, const char *string)
00702         {return args.parse(string);};
00703 
00707     inline const char *argv0() const
00708         {return _argv0;};
00709 
00715     static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3);
00716 
00722     static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3);
00723 
00729     static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3);
00730 
00738     static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL);
00739 
00744     static size_t printf(const char *format, ...) __PRINTF(1, 2);
00745 
00746     static size_t readln(char *address, size_t size);
00747 
00748     static size_t writes(const char *string);
00749 
00750     static size_t read(String& string);
00751 
00752     inline static size_t write(String& string)
00753         {return writes(string.c_str());};
00754 
00761     static size_t printf(pipe_t pipe, const char *format, ...) __PRINTF(2, 3);
00762 
00770     static size_t readln(pipe_t pipe, char *buffer, size_t size);
00771 
00772     static size_t read(pipe_t pipe, String& string);
00773 
00774     static size_t writes(pipe_t pipe, const char *string);
00775 
00776     inline static size_t write(pipe_t pipe, String& string)
00777         {return writes(pipe, string.c_str());};
00778 
00784     inline unsigned argc(void) const
00785         {return _argc;};
00786 
00793     inline char **argv(void) const
00794         {return _argv;};
00795 
00801     inline const char *operator[](unsigned offset)
00802         {return _argv[offset];};
00803 
00807     void detach(downproc_t stopreload = (downproc_t)NULL);
00808 
00812     void restart(void);
00813 
00825     static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
00826 
00838     static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL);
00839 
00848     static void priority(int pri = 1);
00849 
00859     static int  detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL);
00860 
00866     static int wait(shell::pid_t pid);
00867 
00873     static int cancel(shell::pid_t pid);
00874 
00881     static int wait(shell::pipe_t pointer);
00882 
00888     static int cancel(shell::pipe_t pointer);
00889 
00894     inline unsigned operator()(void)
00895         {return _argc;};
00896 
00909     static const char *text(const char *string);
00910 
00920     static const char *texts(const char *singular, const char *plural, unsigned long count);
00921 
00927     static unsigned count(char **argv);
00928 
00929 #ifdef  _MSWINDOWS_
00930 
00931     static inline fd_t input(void)
00932         {return GetStdHandle(STD_INPUT_HANDLE);}; 
00933 
00934     static inline fd_t output(void)
00935         {return GetStdHandle(STD_OUTPUT_HANDLE);}; 
00936 
00937     static inline fd_t error(void)
00938         {return GetStdHandle(STD_ERROR_HANDLE);};
00939 
00940 #else
00941     static inline fd_t input(void)
00942         {return 0;};
00943 
00944     static inline fd_t output(void)
00945         {return 1;};
00946 
00947     static inline fd_t error(void)
00948         {return 2;};
00949 #endif
00950 };
00951 
00955 typedef shell shell_t;
00956 
00960 #undef  _TEXT
00961 #undef  _STR
00962 
00970 inline  const char *_TEXT(const char *s)    
00971     {return shell::text(s);}
00972 
00973 inline const char *_STR(String& s)
00974     {return *s;}
00975 
00976 END_NAMESPACE
00977 
00978 #endif