UCommon
|
00001 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks. 00002 // Copyright (C) 2015 Cherokees of Idaho. 00003 // 00004 // This file is part of GNU uCommon C++. 00005 // 00006 // GNU uCommon C++ is free software: you can redistribute it and/or modify 00007 // it under the terms of the GNU Lesser General Public License as published 00008 // by the Free Software Foundation, either version 3 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // GNU uCommon C++ is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>. 00018 00029 #ifndef _UCOMMON_STRING_H_ 00030 #include <ucommon/string.h> 00031 #endif 00032 00033 #ifndef _UCOMMON_MEMORY_H_ 00034 #include <ucommon/memory.h> 00035 #endif 00036 00037 #ifndef _UCOMMON_BUFFER_H_ 00038 #include <ucommon/buffer.h> 00039 #endif 00040 00041 #ifndef _UCOMMON_SHELL_H_ 00042 #define _UCOMMON_SHELL_H_ 00043 00044 #ifdef _MSWINDOWS_ 00045 #define INVALID_PID_VALUE INVALID_HANDLE_VALUE 00046 #else 00047 #define INVALID_PID_VALUE -1 00048 #endif 00049 00050 #ifdef ERR 00051 #undef ERR 00052 #endif 00053 00054 namespace ucommon { 00055 00063 class __EXPORT shell : public mempager 00064 { 00065 private: 00066 char **_argv; 00067 unsigned _argc; 00068 char *_argv0; 00069 char *_exedir; 00070 LinkedObject *_syms; 00071 00072 class __LOCAL args : public OrderedObject 00073 { 00074 public: 00075 char *item; 00076 }; 00077 00078 class __LOCAL syms : public LinkedObject 00079 { 00080 public: 00081 const char *name; 00082 const char *value; 00083 }; 00084 00090 void collapse(LinkedObject *first); 00091 00095 void set0(char *argv0); 00096 00097 public: 00101 typedef enum {NOARGS = 0, NOARGUMENT, INVARGUMENT, BADOPTION, OPTION_USED, BAD_VALUE, NUMERIC_SET} errmsg_t; 00102 00106 typedef enum {NONE = 0, CONSOLE_LOG, USER_LOG, SYSTEM_LOG, SECURITY_LOG} logmode_t; 00107 00111 typedef enum {FAIL = 0, ERR, WARN, NOTIFY, INFO, DEBUG0} loglevel_t; 00112 00116 typedef enum {NO_NUMERIC, NUMERIC_PLUS, NUMERIC_DASH, NUMERIC_ALL} numeric_t; 00117 00121 typedef enum { 00122 PROGRAM_CONFIG, SERVICE_CONFIG, USER_DEFAULTS, SERVICE_CONTROL, 00123 USER_HOME = USER_DEFAULTS + 3, SERVICE_DATA, SYSTEM_TEMP, USER_CACHE, 00124 SERVICE_CACHE, USER_DATA, USER_CONFIG, SYSTEM_CFG, SYSTEM_ETC, 00125 SYSTEM_VAR, SYSTEM_PREFIX, SYSTEM_SHARE, PROGRAM_PLUGINS, 00126 PROGRAM_TEMP} path_t; 00127 00131 typedef bool (*logproc_t)(loglevel_t level, const char *text); 00132 00136 typedef cpr_service_t mainproc_t; 00137 00141 typedef void (*exitproc_t)(void); 00142 00143 #ifdef _MSWINDOWS_ 00144 typedef HANDLE pid_t; 00145 #else 00146 00149 typedef int pid_t; 00150 #endif 00151 00158 static const char *errmsg(errmsg_t id); 00159 00166 static void errmsg(errmsg_t id, const char *text); 00167 00174 class __EXPORT errormap 00175 { 00176 public: 00177 inline errormap(errmsg_t id, const char *text) 00178 {shell::errmsg(id, text);} 00179 }; 00180 00188 class __EXPORT Option : public LinkedObject 00189 { 00190 public: 00191 char short_option; 00192 const char *long_option; 00193 const char *uses_option; 00194 const char *help_string; 00195 bool trigger_option; 00196 00204 Option(char short_option = 0, const char *long_option = NULL, const char *value_type = NULL, const char *help = NULL); 00205 00206 virtual ~Option(); 00207 00208 static LinkedObject *first(void); 00209 00214 void disable(void); 00215 00221 virtual const char *assign(const char *value) = 0; 00222 00223 static void reset(void); 00224 }; 00225 00233 class __EXPORT flagopt : public Option 00234 { 00235 private: 00236 unsigned counter; 00237 bool single; 00238 00239 virtual const char *assign(const char *value); 00240 00241 public: 00242 flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true); 00243 00244 inline operator bool() const 00245 {return counter > 0;} 00246 00247 inline bool operator!() const 00248 {return counter == 0;} 00249 00250 inline operator unsigned() const 00251 {return counter;} 00252 00253 inline unsigned operator*() const 00254 {return counter;} 00255 00256 inline void set(unsigned value = 1) 00257 {counter = value;} 00258 }; 00259 00265 class __EXPORT groupopt : public Option 00266 { 00267 private: 00268 virtual const char *assign(const char *value); 00269 00270 public: 00271 groupopt(const char *help); 00272 }; 00273 00280 class __EXPORT stringopt : public Option 00281 { 00282 private: 00283 bool used; 00284 00285 protected: 00286 const char *text; 00287 00288 virtual const char *assign(const char *value); 00289 00290 public: 00291 stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL); 00292 00293 inline void set(const char *string) 00294 {text = string;} 00295 00296 inline operator bool() const 00297 {return used;} 00298 00299 inline bool operator!() const 00300 {return !used;} 00301 00302 inline operator const char *() const 00303 {return text;} 00304 00305 inline const char *operator*() const 00306 {return text;} 00307 }; 00308 00315 class __EXPORT charopt : public Option 00316 { 00317 private: 00318 bool used; 00319 00320 protected: 00321 char code; 00322 00323 virtual const char *assign(const char *value); 00324 00325 public: 00326 charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' '); 00327 00328 inline void set(char value) 00329 {code = value;} 00330 00331 inline operator bool() const 00332 {return used;} 00333 00334 inline bool operator!() const 00335 {return !used;} 00336 00337 inline operator char() const 00338 {return code;} 00339 00340 inline char operator*() const 00341 {return code;} 00342 }; 00343 00350 class __EXPORT numericopt : public Option 00351 { 00352 private: 00353 bool used; 00354 00355 protected: 00356 long number; 00357 00358 virtual const char *assign(const char *value); 00359 00360 public: 00361 numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00362 00363 inline void set(long value) 00364 {number = value;} 00365 00366 inline operator bool() const 00367 {return used;} 00368 00369 inline bool operator!() const 00370 {return !used;} 00371 00372 inline operator long() const 00373 {return number;} 00374 00375 inline long operator*() const 00376 {return number;} 00377 }; 00378 00387 class __EXPORT counteropt : public Option 00388 { 00389 private: 00390 bool used; 00391 00392 protected: 00393 long number; 00394 00395 virtual const char *assign(const char *value); 00396 00397 public: 00398 counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00399 00400 inline void set(long value) 00401 {number = value;} 00402 00403 inline operator bool() const 00404 {return used;} 00405 00406 inline bool operator!() const 00407 {return !used;} 00408 00409 inline operator long() const 00410 {return number;} 00411 00412 inline long operator*() const 00413 {return number;} 00414 }; 00415 00423 shell(const char *string, size_t pagesize = 0); 00424 00433 shell(int argc, char **argv, size_t pagesize = 0); 00434 00439 shell(size_t pagesize = 0); 00440 00441 static void setNumeric(numeric_t); 00442 00443 static long getNumeric(void); 00444 00448 static void help(void); 00449 00457 static int system(const char *command, const char **env = NULL); 00458 00465 static int systemf(const char *format, ...) __PRINTF(1,2); 00466 00471 static void relocate(const char *argv0); 00472 00479 static String path(path_t id); 00480 00485 static String userid(void); 00486 00493 static String path(path_t id, const char *directory); 00494 00500 static String path(String& prefix, const char *directory); 00501 00513 static void bind(const char *name); 00514 00524 static void rebind(const char *name = NULL); 00525 00531 char **parse(const char *string); 00532 00541 void parse(int argc, char **argv); 00542 00550 const char *env(const char *name, const char *value = NULL); 00551 00552 inline const char *getenv(const char *name, const char *value = NULL) 00553 {return env(name, value);} 00554 00561 const char *get(const char *name, const char *value = NULL); 00562 00563 inline const char *getsym(const char *name, const char *value = NULL) 00564 {return get(name, value);} 00565 00571 void set(const char *name, const char *value); 00572 00573 inline void setsym(const char *name, const char *value) 00574 {return set(name, value);} 00575 00581 bool is_sym(const char *name) const; 00582 00588 char *getargv0(char **argv); 00589 00597 char **getargv(char **argv); 00598 00605 void restart(char *argv0, char **argv, char **list); 00606 00610 inline const char *argv0() const 00611 {return _argv0;} 00612 00616 inline const char *execdir() const 00617 {return _exedir;} 00618 00623 static void error(const char *format, ...) __PRINTF(1, 2); 00624 00630 static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3); 00631 00632 00638 static inline int condition(bool test, int exitcode) 00639 { return (test) ? exitcode : 0;} 00640 00646 static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3); 00647 00653 static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00654 00660 static void security(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00661 00669 static void log(const char *name, loglevel_t level = ERR, logmode_t mode = USER_LOG, logproc_t handler = (logproc_t)NULL); 00670 00675 static size_t printf(const char *format, ...) __PRINTF(1, 2); 00676 00677 static size_t readln(char *address, size_t size); 00678 00679 static size_t writes(const char *string); 00680 00681 static size_t read(String& string); 00682 00683 inline static size_t write(String& string) 00684 {return writes(string.c_str());} 00685 00691 inline unsigned argc(void) const 00692 {return _argc;} 00693 00700 inline char **argv(void) const 00701 {return _argv;} 00702 00708 inline const char *operator[](unsigned offset) 00709 {return _argv[offset];} 00710 00711 static void exiting(exitproc_t); 00712 00716 void detach(mainproc_t mainentry = (mainproc_t)NULL); 00717 00721 void restart(void); 00722 00734 static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00735 00744 static void priority(int pri = 1); 00745 00755 static int detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00756 00761 static void release(int exit_code = 0); 00762 00768 static int wait(shell::pid_t pid); 00769 00775 static int cancel(shell::pid_t pid); 00776 00781 inline unsigned operator()(void) const 00782 {return _argc;} 00783 00796 static const char *text(const char *string); 00797 00807 static const char *texts(const char *singular, const char *plural, unsigned long count); 00808 00814 static unsigned count(char **argv); 00815 00816 #ifdef _MSWINDOWS_ 00817 00818 static inline fd_t input(void) 00819 {return GetStdHandle(STD_INPUT_HANDLE);} 00820 00821 static inline fd_t output(void) 00822 {return GetStdHandle(STD_OUTPUT_HANDLE);} 00823 00824 static inline fd_t error(void) 00825 {return GetStdHandle(STD_ERROR_HANDLE);} 00826 00827 #else 00828 static inline fd_t input(void) 00829 {return 0;} 00830 00831 static inline fd_t output(void) 00832 {return 1;} 00833 00834 static inline fd_t error(void) 00835 {return 2;} 00836 #endif 00837 00838 static int inkey(const char *prompt = NULL); 00839 00840 static char *getpass(const char *prompt, char *buffer, size_t size); 00841 00842 static char *getline(const char *prompt, char *buffer, size_t size); 00843 00844 }; 00845 00849 typedef shell shell_t; 00850 00854 #undef _TEXT 00855 #undef _STR 00856 #define _STR(x) (const char *)(x) 00857 00865 inline const char *_TEXT(const char *s) 00866 {return shell::text(s);} 00867 00868 } // namespace ucommon 00869 00870 #endif