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 #ifdef ERR 00050 #undef ERR 00051 #endif 00052 00053 NAMESPACE_UCOMMON 00054 00062 class __EXPORT shell : public mempager 00063 { 00064 private: 00065 char **_argv; 00066 unsigned _argc; 00067 char *_argv0; 00068 char *_exedir; 00069 LinkedObject *_syms; 00070 00071 class __LOCAL args : public OrderedObject 00072 { 00073 public: 00074 char *item; 00075 }; 00076 00077 class __LOCAL syms : public LinkedObject 00078 { 00079 public: 00080 const char *name; 00081 const char *value; 00082 }; 00083 00089 void collapse(LinkedObject *first); 00090 00094 void set0(char *argv0); 00095 00096 public: 00100 typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE, NUMERIC_SET} errmsg_t; 00101 00105 typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG, SECURITY_LOG} logmode_t; 00106 00110 typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t; 00111 00115 typedef enum {NO_NUMERIC, NUMERIC_PLUS, NUMERIC_DASH, NUMERIC_ALL} numeric_t; 00116 00120 typedef enum { 00121 PROGRAM_CONFIG, SERVICE_CONFIG, USER_DEFAULTS, SERVICE_CONTROL, 00122 USER_HOME = USER_DEFAULTS + 3, SERVICE_DATA, SYSTEM_TEMP, USER_CACHE, 00123 SERVICE_CACHE, USER_DATA, USER_CONFIG, SYSTEM_CFG, SYSTEM_ETC, 00124 SYSTEM_VAR, SYSTEM_PREFIX, SYSTEM_SHARE, PROGRAM_PLUGINS, 00125 PROGRAM_TEMP} path_t; 00126 00130 typedef bool (*logproc_t)(loglevel_t level, const char *text); 00131 00135 typedef cpr_service_t mainproc_t; 00136 00140 typedef void (*exitproc_t)(void); 00141 00142 #ifdef _MSWINDOWS_ 00143 typedef HANDLE pid_t; 00144 #else 00145 00148 typedef int pid_t; 00149 #endif 00150 00154 typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t; 00155 00164 class __EXPORT pipeio 00165 { 00166 protected: 00167 friend class shell; 00168 00172 pipeio(); 00173 00183 int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00184 00189 int wait(void); 00190 00196 int cancel(void); 00197 00206 size_t read(void *address, size_t size); 00207 00216 size_t write(const void *address, size_t size); 00217 00218 pid_t pid; 00219 fd_t input, output; // input to and output from child process... 00220 int perror, presult; 00221 }; 00222 00229 class __EXPORT iobuf : public BufferProtocol, private pipeio 00230 { 00231 protected: 00232 friend class shell; 00233 00234 int ioerror; 00235 00236 virtual int _err(void) const; 00237 virtual void _clear(void); 00238 00239 virtual size_t _push(const char *address, size_t size); 00240 virtual size_t _pull(char *address, size_t size); 00241 00242 public: 00248 iobuf(size_t size = 0); 00249 00260 iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00261 00266 ~iobuf(); 00267 00276 void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00277 00282 void close(void); 00283 00288 void cancel(void); 00289 }; 00290 00294 typedef iobuf io_t; 00295 00299 typedef pipeio *pipe_t; 00300 00307 static const char *errmsg(errmsg_t id); 00308 00315 static void errmsg(errmsg_t id, const char *text); 00316 00323 class __EXPORT errormap 00324 { 00325 public: 00326 inline errormap(errmsg_t id, const char *text) 00327 {shell::errmsg(id, text);}; 00328 }; 00329 00337 class __EXPORT Option : public OrderedObject 00338 { 00339 public: 00340 char short_option; 00341 const char *long_option; 00342 const char *uses_option; 00343 const char *help_string; 00344 bool trigger_option; 00345 00353 Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL); 00354 00355 virtual ~Option(); 00356 00357 static LinkedObject *first(void); 00358 00363 void disable(void); 00364 00370 virtual const char *assign(const char *value) = 0; 00371 00372 static void reset(void); 00373 }; 00374 00382 class __EXPORT flagopt : public Option 00383 { 00384 private: 00385 unsigned counter; 00386 bool single; 00387 00388 virtual const char *assign(const char *value); 00389 00390 public: 00391 flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true); 00392 00393 inline operator bool() 00394 {return counter > 0;}; 00395 00396 inline bool operator!() 00397 {return counter == 0;}; 00398 00399 inline operator unsigned() 00400 {return counter;}; 00401 00402 inline unsigned operator*() 00403 {return counter;}; 00404 00405 inline void set(unsigned value = 1) 00406 {counter = value;}; 00407 }; 00408 00414 class __EXPORT groupopt : public Option 00415 { 00416 private: 00417 virtual const char *assign(const char *value); 00418 00419 public: 00420 groupopt(const char *help); 00421 }; 00422 00429 class __EXPORT stringopt : public Option 00430 { 00431 private: 00432 bool used; 00433 00434 protected: 00435 const char *text; 00436 00437 virtual const char *assign(const char *value); 00438 00439 public: 00440 stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL); 00441 00442 inline void set(const char *string) 00443 {text = string;}; 00444 00445 inline operator bool() 00446 {return used;}; 00447 00448 inline bool operator!() 00449 {return !used;}; 00450 00451 inline operator const char *() 00452 {return text;}; 00453 00454 inline const char *operator*() 00455 {return text;}; 00456 }; 00457 00464 class __EXPORT charopt : public Option 00465 { 00466 private: 00467 bool used; 00468 00469 protected: 00470 char code; 00471 00472 virtual const char *assign(const char *value); 00473 00474 public: 00475 charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' '); 00476 00477 inline void set(char value) 00478 {code = value;}; 00479 00480 inline operator bool() 00481 {return used;}; 00482 00483 inline bool operator!() 00484 {return !used;}; 00485 00486 inline operator char() 00487 {return code;}; 00488 00489 inline char operator*() 00490 {return code;}; 00491 }; 00492 00499 class __EXPORT numericopt : public Option 00500 { 00501 private: 00502 bool used; 00503 00504 protected: 00505 long number; 00506 00507 virtual const char *assign(const char *value); 00508 00509 public: 00510 numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00511 00512 inline void set(long value) 00513 {number = value;}; 00514 00515 inline operator bool() 00516 {return used;}; 00517 00518 inline bool operator!() 00519 {return !used;}; 00520 00521 inline operator long() 00522 {return number;}; 00523 00524 inline long operator*() 00525 {return number;}; 00526 }; 00527 00536 class __EXPORT counteropt : public Option 00537 { 00538 private: 00539 bool used; 00540 00541 protected: 00542 long number; 00543 00544 virtual const char *assign(const char *value); 00545 00546 public: 00547 counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00548 00549 inline void set(long value) 00550 {number = value;}; 00551 00552 inline operator bool() 00553 {return used;}; 00554 00555 inline bool operator!() 00556 {return !used;}; 00557 00558 inline operator long() 00559 {return number;}; 00560 00561 inline long operator*() 00562 {return number;}; 00563 }; 00564 00572 shell(const char *string, size_t pagesize = 0); 00573 00582 shell(int argc, char **argv, size_t pagesize = 0); 00583 00588 shell(size_t pagesize = 0); 00589 00590 static void setNumeric(numeric_t); 00591 00592 static long getNumeric(void); 00593 00597 static void help(void); 00598 00606 static int system(const char *command, const char **env = NULL); 00607 00614 static int systemf(const char *format, ...) __PRINTF(1,2); 00615 00620 static void relocate(const char *argv0); 00621 00628 static String path(path_t id); 00629 00634 static String userid(void); 00635 00642 static String path(path_t id, const char *directory); 00643 00649 static String path(String& prefix, const char *directory); 00650 00662 static void bind(const char *name); 00663 00673 static void rebind(const char *name = NULL); 00674 00680 char **parse(const char *string); 00681 00690 void parse(int argc, char **argv); 00691 00699 const char *getenv(const char *name, const char *value = NULL); 00700 00707 const char *getsym(const char *name, const char *value = NULL); 00708 00714 void setsym(const char *name, const char *value); 00715 00721 bool issym(const char *name); 00722 00728 char *getargv0(char **argv); 00729 00737 char **getargv(char **argv); 00738 00745 void restart(char *argv0, char **argv, char **list); 00746 00753 inline static char **parse(shell &args, const char *string) 00754 {return args.parse(string);} 00755 00759 inline const char *argv0() const 00760 {return _argv0;} 00761 00765 inline const char *execdir() const 00766 {return _exedir;} 00767 00772 static void error(const char *format, ...) __PRINTF(1, 2); 00773 00779 static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3); 00780 00781 00787 static inline int condition(bool test, int exitcode) 00788 { return (test) ? exitcode : 0;}; 00789 00795 static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3); 00796 00802 static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00803 00809 static void security(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00810 00818 static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL); 00819 00824 static size_t printf(const char *format, ...) __PRINTF(1, 2); 00825 00826 static size_t readln(char *address, size_t size); 00827 00828 static size_t writes(const char *string); 00829 00830 static size_t read(String& string); 00831 00832 inline static size_t write(String& string) 00833 {return writes(string.c_str());}; 00834 00841 static size_t printf(pipe_t pipe, const char *format, ...) __PRINTF(2, 3); 00842 00850 static size_t readln(pipe_t pipe, char *buffer, size_t size); 00851 00852 static size_t read(pipe_t pipe, String& string); 00853 00854 static size_t writes(pipe_t pipe, const char *string); 00855 00856 inline static size_t write(pipe_t pipe, String& string) 00857 {return writes(pipe, string.c_str());}; 00858 00864 inline unsigned argc(void) const 00865 {return _argc;}; 00866 00873 inline char **argv(void) const 00874 {return _argv;}; 00875 00881 inline const char *operator[](unsigned offset) 00882 {return _argv[offset];}; 00883 00884 static void exiting(exitproc_t); 00885 00889 void detach(mainproc_t mainentry = (mainproc_t)NULL); 00890 00894 void restart(void); 00895 00907 static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00908 00920 static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00921 00930 static void priority(int pri = 1); 00931 00941 static int detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00942 00947 static void release(int exit_code = 0); 00948 00954 static int wait(shell::pid_t pid); 00955 00961 static int cancel(shell::pid_t pid); 00962 00969 static int wait(shell::pipe_t pointer); 00970 00976 static int cancel(shell::pipe_t pointer); 00977 00982 inline unsigned operator()(void) 00983 {return _argc;}; 00984 00997 static const char *text(const char *string); 00998 01008 static const char *texts(const char *singular, const char *plural, unsigned long count); 01009 01015 static unsigned count(char **argv); 01016 01017 #ifdef _MSWINDOWS_ 01018 01019 static inline fd_t input(void) 01020 {return GetStdHandle(STD_INPUT_HANDLE);}; 01021 01022 static inline fd_t output(void) 01023 {return GetStdHandle(STD_OUTPUT_HANDLE);}; 01024 01025 static inline fd_t error(void) 01026 {return GetStdHandle(STD_ERROR_HANDLE);}; 01027 01028 #else 01029 static inline fd_t input(void) 01030 {return 0;}; 01031 01032 static inline fd_t output(void) 01033 {return 1;}; 01034 01035 static inline fd_t error(void) 01036 {return 2;}; 01037 #endif 01038 01039 static int inkey(const char *prompt = NULL); 01040 01041 static char *getpass(const char *prompt, char *buffer, size_t size); 01042 01043 static char *getline(const char *prompt, char *buffer, size_t size); 01044 01045 }; 01046 01050 typedef shell shell_t; 01051 01055 #undef _TEXT 01056 #undef _STR 01057 01065 inline const char *_TEXT(const char *s) 01066 {return shell::text(s);} 01067 01068 inline const char *_STR(String& s) 01069 {return *s;} 01070 01071 END_NAMESPACE 01072 01073 #endif