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 class __LOCAL args : public OrderedObject 00067 { 00068 public: 00069 char *item; 00070 }; 00071 00072 class __LOCAL syms : public LinkedObject 00073 { 00074 public: 00075 const char *name; 00076 const char *value; 00077 }; 00078 00084 void collapse(LinkedObject *first); 00085 00089 void set0(char *argv0); 00090 00091 public: 00095 typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE, NUMERIC_SET} errmsg_t; 00096 00100 typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG, SECURITY_LOG} logmode_t; 00101 00105 typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t; 00106 00110 typedef enum {NO_NUMERIC, NUMERIC_PLUS, NUMERIC_DASH, NUMERIC_ALL} numeric_t; 00111 00115 typedef enum { 00116 PROGRAM_CONFIG, SERVICE_CONFIG, USER_DEFAULTS, SYSTEM_CERTIFICATES, 00117 SYSTEM_KEYS, USER_HOME, SERVICE_DATA, SYSTEM_TEMP, USER_CACHE, 00118 SERVICE_CACHE, USER_DATA, USER_CONFIG, SYSTEM_CFG, SYSTEM_ETC, 00119 SYSTEM_VAR, SYSTEM_PREFIX, SYSTEM_SHARE, PROGRAM_PLUGINS, 00120 PROGRAM_TEMP} path_t; 00121 00125 typedef bool (*logproc_t)(loglevel_t level, const char *text); 00126 00130 typedef cpr_service_t mainproc_t; 00131 00135 typedef void (*exitproc_t)(void); 00136 00137 #ifdef _MSWINDOWS_ 00138 typedef HANDLE pid_t; 00139 #else 00140 00143 typedef int pid_t; 00144 #endif 00145 00149 typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t; 00150 00159 class __EXPORT pipeio 00160 { 00161 protected: 00162 friend class shell; 00163 00167 pipeio(); 00168 00178 int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00179 00184 int wait(void); 00185 00191 int cancel(void); 00192 00201 size_t read(void *address, size_t size); 00202 00211 size_t write(const void *address, size_t size); 00212 00213 pid_t pid; 00214 fd_t input, output; // input to and output from child process... 00215 int perror, presult; 00216 }; 00217 00224 class __EXPORT iobuf : public BufferProtocol, private pipeio 00225 { 00226 protected: 00227 friend class shell; 00228 00229 int ioerror; 00230 00231 virtual int _err(void) const; 00232 virtual void _clear(void); 00233 00234 virtual size_t _push(const char *address, size_t size); 00235 virtual size_t _pull(char *address, size_t size); 00236 00237 public: 00243 iobuf(size_t size = 0); 00244 00255 iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00256 00261 ~iobuf(); 00262 00271 void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00272 00277 void close(void); 00278 00283 void cancel(void); 00284 }; 00285 00289 typedef iobuf io_t; 00290 00294 typedef pipeio *pipe_t; 00295 00302 static const char *errmsg(errmsg_t id); 00303 00310 static void errmsg(errmsg_t id, const char *text); 00311 00318 class __EXPORT errormap 00319 { 00320 public: 00321 inline errormap(errmsg_t id, const char *text) 00322 {shell::errmsg(id, text);}; 00323 }; 00324 00332 class __EXPORT Option : public OrderedObject 00333 { 00334 public: 00335 char short_option; 00336 const char *long_option; 00337 const char *uses_option; 00338 const char *help_string; 00339 bool trigger_option; 00340 00348 Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL); 00349 00350 virtual ~Option(); 00351 00352 static LinkedObject *first(void); 00353 00358 void disable(void); 00359 00365 virtual const char *assign(const char *value) = 0; 00366 00367 static void reset(void); 00368 }; 00369 00377 class __EXPORT flagopt : public Option 00378 { 00379 private: 00380 unsigned counter; 00381 bool single; 00382 00383 virtual const char *assign(const char *value); 00384 00385 public: 00386 flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true); 00387 00388 inline operator bool() 00389 {return counter > 0;}; 00390 00391 inline bool operator!() 00392 {return counter == 0;}; 00393 00394 inline operator unsigned() 00395 {return counter;}; 00396 00397 inline unsigned operator*() 00398 {return counter;}; 00399 00400 inline void set(unsigned value = 1) 00401 {counter = value;}; 00402 }; 00403 00409 class __EXPORT groupopt : public Option 00410 { 00411 private: 00412 virtual const char *assign(const char *value); 00413 00414 public: 00415 groupopt(const char *help); 00416 }; 00417 00424 class __EXPORT stringopt : public Option 00425 { 00426 private: 00427 bool used; 00428 00429 protected: 00430 const char *text; 00431 00432 virtual const char *assign(const char *value); 00433 00434 public: 00435 stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL); 00436 00437 inline void set(const char *string) 00438 {text = string;}; 00439 00440 inline operator bool() 00441 {return used;}; 00442 00443 inline bool operator!() 00444 {return !used;}; 00445 00446 inline operator const char *() 00447 {return text;}; 00448 00449 inline const char *operator*() 00450 {return text;}; 00451 }; 00452 00459 class __EXPORT charopt : public Option 00460 { 00461 private: 00462 bool used; 00463 00464 protected: 00465 char code; 00466 00467 virtual const char *assign(const char *value); 00468 00469 public: 00470 charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' '); 00471 00472 inline void set(char value) 00473 {code = value;}; 00474 00475 inline operator bool() 00476 {return used;}; 00477 00478 inline bool operator!() 00479 {return !used;}; 00480 00481 inline operator char() 00482 {return code;}; 00483 00484 inline char operator*() 00485 {return code;}; 00486 }; 00487 00494 class __EXPORT numericopt : public Option 00495 { 00496 private: 00497 bool used; 00498 00499 protected: 00500 long number; 00501 00502 virtual const char *assign(const char *value); 00503 00504 public: 00505 numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00506 00507 inline void set(long value) 00508 {number = value;}; 00509 00510 inline operator bool() 00511 {return used;}; 00512 00513 inline bool operator!() 00514 {return !used;}; 00515 00516 inline operator long() 00517 {return number;}; 00518 00519 inline long operator*() 00520 {return number;}; 00521 }; 00522 00531 class __EXPORT counteropt : public Option 00532 { 00533 private: 00534 bool used; 00535 00536 protected: 00537 long number; 00538 00539 virtual const char *assign(const char *value); 00540 00541 public: 00542 counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00543 00544 inline void set(long value) 00545 {number = value;}; 00546 00547 inline operator bool() 00548 {return used;}; 00549 00550 inline bool operator!() 00551 {return !used;}; 00552 00553 inline operator long() 00554 {return number;}; 00555 00556 inline long operator*() 00557 {return number;}; 00558 }; 00559 00567 shell(const char *string, size_t pagesize = 0); 00568 00577 shell(int argc, char **argv, size_t pagesize = 0); 00578 00583 shell(size_t pagesize = 0); 00584 00585 static void setNumeric(numeric_t); 00586 00587 static long getNumeric(void); 00588 00592 static void help(void); 00593 00601 static int system(const char *command, const char **env = NULL); 00602 00609 static int systemf(const char *format, ...) __PRINTF(1,2); 00610 00615 static void relocate(const char *argv0); 00616 00623 static String path(path_t id); 00624 00629 static String userid(void); 00630 00636 static String path(path_t id, const char *directory); 00637 00649 static void bind(const char *name); 00650 00660 static void rebind(const char *name = NULL); 00661 00667 char **parse(const char *string); 00668 00677 void parse(int argc, char **argv); 00678 00686 const char *getenv(const char *name, const char *value = NULL); 00687 00694 const char *getsym(const char *name, const char *value = NULL); 00695 00701 void setsym(const char *name, const char *value); 00702 00708 bool issym(const char *name); 00709 00715 char *getargv0(char **argv); 00716 00724 char **getargv(char **argv); 00725 00732 void restart(char *argv0, char **argv, char **list); 00733 00740 inline static char **parse(shell &args, const char *string) 00741 {return args.parse(string);}; 00742 00746 inline const char *argv0() const 00747 {return _argv0;}; 00748 00754 static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3); 00755 00761 static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3); 00762 00768 static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00769 00775 static void security(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00776 00784 static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL); 00785 00790 static size_t printf(const char *format, ...) __PRINTF(1, 2); 00791 00792 static size_t readln(char *address, size_t size); 00793 00794 static size_t writes(const char *string); 00795 00796 static size_t read(String& string); 00797 00798 inline static size_t write(String& string) 00799 {return writes(string.c_str());}; 00800 00807 static size_t printf(pipe_t pipe, const char *format, ...) __PRINTF(2, 3); 00808 00816 static size_t readln(pipe_t pipe, char *buffer, size_t size); 00817 00818 static size_t read(pipe_t pipe, String& string); 00819 00820 static size_t writes(pipe_t pipe, const char *string); 00821 00822 inline static size_t write(pipe_t pipe, String& string) 00823 {return writes(pipe, string.c_str());}; 00824 00830 inline unsigned argc(void) const 00831 {return _argc;}; 00832 00839 inline char **argv(void) const 00840 {return _argv;}; 00841 00847 inline const char *operator[](unsigned offset) 00848 {return _argv[offset];}; 00849 00850 static void exiting(exitproc_t); 00851 00855 void detach(mainproc_t mainentry = (mainproc_t)NULL); 00856 00860 void restart(void); 00861 00873 static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00874 00886 static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00887 00896 static void priority(int pri = 1); 00897 00907 static int detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00908 00914 static int wait(shell::pid_t pid); 00915 00921 static int cancel(shell::pid_t pid); 00922 00929 static int wait(shell::pipe_t pointer); 00930 00936 static int cancel(shell::pipe_t pointer); 00937 00942 inline unsigned operator()(void) 00943 {return _argc;}; 00944 00957 static const char *text(const char *string); 00958 00968 static const char *texts(const char *singular, const char *plural, unsigned long count); 00969 00975 static unsigned count(char **argv); 00976 00977 #ifdef _MSWINDOWS_ 00978 00979 static inline fd_t input(void) 00980 {return GetStdHandle(STD_INPUT_HANDLE);}; 00981 00982 static inline fd_t output(void) 00983 {return GetStdHandle(STD_OUTPUT_HANDLE);}; 00984 00985 static inline fd_t error(void) 00986 {return GetStdHandle(STD_ERROR_HANDLE);}; 00987 00988 #else 00989 static inline fd_t input(void) 00990 {return 0;}; 00991 00992 static inline fd_t output(void) 00993 {return 1;}; 00994 00995 static inline fd_t error(void) 00996 {return 2;}; 00997 #endif 00998 }; 00999 01003 typedef shell shell_t; 01004 01008 #undef _TEXT 01009 #undef _STR 01010 01018 inline const char *_TEXT(const char *s) 01019 {return shell::text(s);} 01020 01021 inline const char *_STR(String& s) 01022 {return *s;} 01023 01024 END_NAMESPACE 01025 01026 #endif