UCommon
|
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