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