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} 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 bool (*logproc_t)(loglevel_t level, const char *text); 00111 00115 typedef cpr_service_t mainproc_t; 00116 00120 typedef void (*exitproc_t)(void); 00121 00122 #ifdef _MSWINDOWS_ 00123 typedef HANDLE pid_t; 00124 #else 00125 00128 typedef int pid_t; 00129 #endif 00130 00134 typedef enum {RD = BufferProtocol::BUF_RD, WR = BufferProtocol::BUF_WR, RDWR = BufferProtocol::BUF_RDWR} pmode_t; 00135 00144 class __EXPORT pipeio 00145 { 00146 protected: 00147 friend class shell; 00148 00152 pipeio(); 00153 00163 int spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00164 00169 int wait(void); 00170 00176 int cancel(void); 00177 00186 size_t read(void *address, size_t size); 00187 00196 size_t write(const void *address, size_t size); 00197 00198 pid_t pid; 00199 fd_t input, output; // input to and output from child process... 00200 int perror, presult; 00201 }; 00202 00209 class __EXPORT iobuf : public BufferProtocol, private pipeio 00210 { 00211 protected: 00212 friend class shell; 00213 00214 int ioerror; 00215 00216 virtual int _err(void) const; 00217 virtual void _clear(void); 00218 00219 virtual size_t _push(const char *address, size_t size); 00220 virtual size_t _pull(char *address, size_t size); 00221 00222 public: 00228 iobuf(size_t size = 0); 00229 00240 iobuf(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00241 00246 ~iobuf(); 00247 00256 void open(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00257 00262 void close(void); 00263 00268 void cancel(void); 00269 }; 00270 00274 typedef iobuf io_t; 00275 00279 typedef pipeio *pipe_t; 00280 00287 static const char *errmsg(errmsg_t id); 00288 00295 static void errmsg(errmsg_t id, const char *text); 00296 00303 class __EXPORT errormap 00304 { 00305 public: 00306 inline errormap(errmsg_t id, const char *text) 00307 {shell::errmsg(id, text);}; 00308 }; 00309 00317 class __EXPORT Option : public OrderedObject 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 static LinkedObject *first(void); 00338 00343 void disable(void); 00344 00350 virtual const char *assign(const char *value) = 0; 00351 00352 static void reset(void); 00353 }; 00354 00362 class __EXPORT flagopt : public Option 00363 { 00364 private: 00365 unsigned counter; 00366 bool single; 00367 00368 virtual const char *assign(const char *value); 00369 00370 public: 00371 flagopt(char short_option, const char *long_option = NULL, const char *help = NULL, bool single_use = true); 00372 00373 inline operator bool() 00374 {return counter > 0;}; 00375 00376 inline bool operator!() 00377 {return counter == 0;}; 00378 00379 inline operator unsigned() 00380 {return counter;}; 00381 00382 inline unsigned operator*() 00383 {return counter;}; 00384 00385 inline void set(unsigned value = 1) 00386 {counter = value;}; 00387 }; 00388 00394 class __EXPORT groupopt : public Option 00395 { 00396 private: 00397 virtual const char *assign(const char *value); 00398 00399 public: 00400 groupopt(const char *help); 00401 }; 00402 00409 class __EXPORT stringopt : public Option 00410 { 00411 private: 00412 bool used; 00413 00414 protected: 00415 const char *text; 00416 00417 virtual const char *assign(const char *value); 00418 00419 public: 00420 stringopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "text", const char *def_text = NULL); 00421 00422 inline void set(const char *string) 00423 {text = string;}; 00424 00425 inline operator bool() 00426 {return used;}; 00427 00428 inline bool operator!() 00429 {return !used;}; 00430 00431 inline operator const char *() 00432 {return text;}; 00433 00434 inline const char *operator*() 00435 {return text;}; 00436 }; 00437 00444 class __EXPORT charopt : public Option 00445 { 00446 private: 00447 bool used; 00448 00449 protected: 00450 char code; 00451 00452 virtual const char *assign(const char *value); 00453 00454 public: 00455 charopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "char", char default_code = ' '); 00456 00457 inline void set(char value) 00458 {code = value;}; 00459 00460 inline operator bool() 00461 {return used;}; 00462 00463 inline bool operator!() 00464 {return !used;}; 00465 00466 inline operator char() 00467 {return code;}; 00468 00469 inline char operator*() 00470 {return code;}; 00471 }; 00472 00479 class __EXPORT numericopt : public Option 00480 { 00481 private: 00482 bool used; 00483 00484 protected: 00485 long number; 00486 00487 virtual const char *assign(const char *value); 00488 00489 public: 00490 numericopt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00491 00492 inline void set(long value) 00493 {number = value;}; 00494 00495 inline operator bool() 00496 {return used;}; 00497 00498 inline bool operator!() 00499 {return !used;}; 00500 00501 inline operator long() 00502 {return number;}; 00503 00504 inline long operator*() 00505 {return number;}; 00506 }; 00507 00516 class __EXPORT counteropt : public Option 00517 { 00518 private: 00519 bool used; 00520 00521 protected: 00522 long number; 00523 00524 virtual const char *assign(const char *value); 00525 00526 public: 00527 counteropt(char short_option, const char *long_option = NULL, const char *help = NULL, const char *type = "numeric", long def_value = 0); 00528 00529 inline void set(long value) 00530 {number = value;}; 00531 00532 inline operator bool() 00533 {return used;}; 00534 00535 inline bool operator!() 00536 {return !used;}; 00537 00538 inline operator long() 00539 {return number;}; 00540 00541 inline long operator*() 00542 {return number;}; 00543 }; 00544 00552 shell(const char *string, size_t pagesize = 0); 00553 00562 shell(int argc, char **argv, size_t pagesize = 0); 00563 00568 shell(size_t pagesize = 0); 00569 00573 static void help(void); 00574 00582 static int system(const char *command, const char **env = NULL); 00583 00590 static int systemf(const char *format, ...) __PRINTF(1,2); 00591 00603 static void bind(const char *name); 00604 00614 static void rebind(const char *name = NULL); 00615 00621 char **parse(const char *string); 00622 00631 void parse(int argc, char **argv); 00632 00640 const char *getenv(const char *name, const char *value = NULL); 00641 00648 const char *getsym(const char *name, const char *value = NULL); 00649 00655 void setsym(const char *name, const char *value); 00656 00662 bool issym(const char *name); 00663 00669 char *getargv0(char **argv); 00670 00678 char **getargv(char **argv); 00679 00686 void restart(char *argv0, char **argv, char **list); 00687 00694 inline static char **parse(shell &args, const char *string) 00695 {return args.parse(string);}; 00696 00700 inline const char *argv0() const 00701 {return _argv0;}; 00702 00708 static void errexit(int exitcode, const char *format = NULL, ...) __PRINTF(2, 3); 00709 00715 static void debug(unsigned level, const char *format, ...) __PRINTF(2, 3); 00716 00722 static void log(loglevel_t level, const char *format, ...) __PRINTF(2, 3); 00723 00729 static void security(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 00804 static void exiting(exitproc_t); 00805 00809 void detach(mainproc_t mainentry = (mainproc_t)NULL); 00810 00814 void restart(void); 00815 00827 static shell::pid_t spawn(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00828 00840 static shell::pipe_t spawn(const char *path, char **argv, pmode_t mode, size_t size = 512, char **env = NULL); 00841 00850 static void priority(int pri = 1); 00851 00861 static int detach(const char *path, char **argv, char **env = NULL, fd_t *stdio = NULL); 00862 00868 static int wait(shell::pid_t pid); 00869 00875 static int cancel(shell::pid_t pid); 00876 00883 static int wait(shell::pipe_t pointer); 00884 00890 static int cancel(shell::pipe_t pointer); 00891 00896 inline unsigned operator()(void) 00897 {return _argc;}; 00898 00911 static const char *text(const char *string); 00912 00922 static const char *texts(const char *singular, const char *plural, unsigned long count); 00923 00929 static unsigned count(char **argv); 00930 00931 #ifdef _MSWINDOWS_ 00932 00933 static inline fd_t input(void) 00934 {return GetStdHandle(STD_INPUT_HANDLE);}; 00935 00936 static inline fd_t output(void) 00937 {return GetStdHandle(STD_OUTPUT_HANDLE);}; 00938 00939 static inline fd_t error(void) 00940 {return GetStdHandle(STD_ERROR_HANDLE);}; 00941 00942 #else 00943 static inline fd_t input(void) 00944 {return 0;}; 00945 00946 static inline fd_t output(void) 00947 {return 1;}; 00948 00949 static inline fd_t error(void) 00950 {return 2;}; 00951 #endif 00952 }; 00953 00957 typedef shell shell_t; 00958 00962 #undef _TEXT 00963 #undef _STR 00964 00972 inline const char *_TEXT(const char *s) 00973 {return shell::text(s);} 00974 00975 inline const char *_STR(String& s) 00976 {return *s;} 00977 00978 END_NAMESPACE 00979 00980 #endif