X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/a4d849b7b60b43b71a5fe406ff0d78ccf197d15d..0abb2a2f9d5b1c7fbe7a43619bab5291d7e55f87:/Console.cpp diff --git a/Console.cpp b/Console.cpp index 43012ac..c3ebd77 100644 --- a/Console.cpp +++ b/Console.cpp @@ -249,11 +249,23 @@ void Setup(CYOutput &out, CYDriver &driver, CYOptions &options, bool lower) { driver.Replace(options); } -static CYUTF8String Run(CYPool &pool, int client, CYUTF8String code) { - const char *json; - uint32_t size; +class CYRemote { + public: + virtual CYUTF8String Run(CYPool &pool, CYUTF8String code) = 0; + + inline CYUTF8String Run(CYPool &pool, const std::string &code) { + return Run(pool, CYUTF8String(code.c_str(), code.size())); + } +}; + +class CYLocalRemote : + public CYRemote +{ + public: + virtual CYUTF8String Run(CYPool &pool, CYUTF8String code) { + const char *json; + uint32_t size; - if (client == -1) { mode_ = Running; #ifdef CY_EXECUTE json = CYExecute(CYGetJSContext(), pool, code); @@ -265,34 +277,99 @@ static CYUTF8String Run(CYPool &pool, int client, CYUTF8String code) { size = 0; else size = strlen(json); - } else { + + return CYUTF8String(json, size); + } +}; + +class CYSocketRemote : + public CYRemote +{ + private: + int socket_; + + public: + CYSocketRemote(const char *host, const char *port) { + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_flags = 0; + + struct addrinfo *infos; + _syscall(getaddrinfo(host, port, &hints, &infos)); + + _assert(infos != NULL); try { + for (struct addrinfo *info(infos); info != NULL; info = info->ai_next) { + socket_ = _syscall(socket(info->ai_family, info->ai_socktype, info->ai_protocol)); try { + _syscall(connect(socket_, info->ai_addr, info->ai_addrlen)); + break; + } catch (...) { + _syscall(close(socket_)); + throw; + } + } + } catch (...) { + freeaddrinfo(infos); + throw; + } + } + + virtual CYUTF8String Run(CYPool &pool, CYUTF8String code) { + const char *json; + uint32_t size; + mode_ = Sending; size = code.size; - _assert(CYSendAll(client, &size, sizeof(size))); - _assert(CYSendAll(client, code.data, code.size)); + _assert(CYSendAll(socket_, &size, sizeof(size))); + _assert(CYSendAll(socket_, code.data, code.size)); mode_ = Waiting; - _assert(CYRecvAll(client, &size, sizeof(size))); - if (size == _not(uint32_t)) + _assert(CYRecvAll(socket_, &size, sizeof(size))); + if (size == _not(uint32_t)) { + size = 0; json = NULL; - else { + } else { char *temp(new(pool) char[size + 1]); - _assert(CYRecvAll(client, temp, size)); + _assert(CYRecvAll(socket_, temp, size)); temp[size] = '\0'; json = temp; } mode_ = Working; + + return CYUTF8String(json, size); } +}; - return CYUTF8String(json, size); -} +void InjectLibrary(pid_t, std::ostream &stream, int, const char *const []); -static CYUTF8String Run(CYPool &pool, int client, const std::string &code) { - return Run(pool, client, CYUTF8String(code.c_str(), code.size())); -} +class CYInjectRemote : + public CYRemote +{ + private: + int pid_; + + public: + CYInjectRemote(int pid) : + pid_(pid) + { + // XXX: wait + } + + virtual CYUTF8String Run(CYPool &pool, CYUTF8String code) { + std::ostringstream stream; + const char *args[2] = {"-e", code.data}; + InjectLibrary(pid_, stream, 2, args); + std::string json(stream.str()); + if (!json.empty() && json[json.size() - 1] == '\n') + json.resize(json.size() - 1); + return CYUTF8String(strdup(json.c_str()), json.size()); + } +}; static std::ostream *out_; -static void Output(CYUTF8String json, std::ostream *out, bool expand = false, bool reparse = false) { +static void Output(CYUTF8String json, std::ostream *out, bool reparse = false) { CYPool pool; if (reparse) do { @@ -314,32 +391,10 @@ static void Output(CYUTF8String json, std::ostream *out, bool expand = false, bo const char *data(json.data); size_t size(json.size); - if (data == NULL || out == NULL) + if (size == 0 || out == NULL) return; - if (!expand || - data[0] != '@' && data[0] != '"' && data[0] != '\'' || - data[0] == '@' && data[1] != '"' && data[1] != '\'' - ) - CYLexerHighlight(data, size, *out); - else for (size_t i(0); i != size; ++i) - if (data[i] != '\\') - *out << data[i]; - else switch(data[++i]) { - case '\0': goto done; - case '\\': *out << '\\'; break; - case '\'': *out << '\''; break; - case '"': *out << '"'; break; - case 'b': *out << '\b'; break; - case 'f': *out << '\f'; break; - case 'n': *out << '\n'; break; - case 'r': *out << '\r'; break; - case 't': *out << '\t'; break; - case 'v': *out << '\v'; break; - default: *out << '\\'; --i; break; - } - - done: + CYLexerHighlight(data, size, *out); *out << std::endl; } @@ -347,10 +402,10 @@ int (*append_history$)(int, const char *); static std::string command_; -static int client_; +static CYRemote *remote_; static CYUTF8String Run(CYPool &pool, const std::string &code) { - return Run(pool, client_, code); + return remote_->Run(pool, code); } static char **Complete(const char *word, int start, int end) { @@ -400,6 +455,9 @@ class History { } } void operator +=(std::string command) { + if (HIST_ENTRY *entry = history_get(where_history())) + if (command == entry->line) + return; add_history(command.c_str()); ++histlines_; } @@ -626,9 +684,9 @@ static void CYConsolePrepTerm(int meta) { CYConsoleRemapKeys(vi_movement_keymap); } -static void CYOutputRun(const std::string &code, bool expand = false, bool reparse = false) { +static void CYOutputRun(const std::string &code, bool reparse = false) { CYPool pool; - Output(Run(pool, client_, code), &std::cout, expand, reparse); + Output(Run(pool, code), &std::cout, reparse); } static void Console(CYOptions &options) { @@ -658,7 +716,6 @@ static void Console(CYOptions &options) { bool bypass(false); bool debug(false); - bool expand(false); bool lower(true); bool reparse(false); @@ -674,13 +731,13 @@ static void Console(CYOptions &options) { CYOutputRun(""); - struct sigaction action; - sigemptyset(&action.sa_mask); - action.sa_handler = &sigint; - action.sa_flags = 0; - sigaction(SIGINT, &action, NULL); - for (;;) { + struct sigaction action; + sigemptyset(&action.sa_mask); + action.sa_handler = &sigint; + action.sa_flags = 0; + sigaction(SIGINT, &action, NULL); + if (setjmp(ctrlc_) != 0) { mode_ = Working; *out_ << std::endl; @@ -726,9 +783,6 @@ static void Console(CYOptions &options) { *out_ << "done." << std::endl; } else if (data == "exit") { return; - } else if (data == "expand") { - expand = !expand; - *out_ << "expand == " << (expand ? "true" : "false") << std::endl; } else if (data == "lower") { lower = !lower; *out_ << "lower == " << (lower ? "true" : "false") << std::endl; @@ -798,12 +852,10 @@ static void Console(CYOptions &options) { std::cout << std::endl; } - CYOutputRun(code, expand, reparse); + CYOutputRun(code, reparse); } } -void InjectLibrary(pid_t, int, const char *const []); - static uint64_t CYGetTime() { #ifdef __APPLE__ return mach_absolute_time(); @@ -829,6 +881,8 @@ int Main(int argc, char * const argv[], char const * const envp[]) { const char *host(NULL); const char *port(NULL); + const char *argv0(argv[0]); + optind = 1; for (;;) { @@ -1007,102 +1061,28 @@ int Main(int argc, char * const argv[], char const * const envp[]) { if (argc == 0) script = NULL; else { -#ifdef CY_EXECUTE - // XXX: const_cast?! wtf gcc :( - CYSetArgs(argc - 1, const_cast(argv + 1)); -#endif script = argv[0]; if (strcmp(script, "-") == 0) script = NULL; + --argc; + ++argv; } -#ifdef CY_ATTACH - if (pid == _not(pid_t)) - client_ = -1; - else { - struct Socket { - int fd_; - - Socket(int fd) : - fd_(fd) - { - } - - ~Socket() { - close(fd_); - } - - operator int() { - return fd_; - } - } server(_syscall(socket(PF_UNIX, SOCK_STREAM, 0))); - - struct sockaddr_un address; - memset(&address, 0, sizeof(address)); - address.sun_family = AF_UNIX; - - const char *tmp; -#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) - tmp = "/Library/Caches"; -#else - tmp = "/tmp"; +#ifdef CY_EXECUTE + // XXX: const_cast?! wtf gcc :( + CYSetArgs(argv0, script, argc, const_cast(argv)); #endif - sprintf(address.sun_path, "%s/.s.cy.%u", tmp, getpid()); - unlink(address.sun_path); - - struct File { - const char *path_; - - File(const char *path) : - path_(path) - { - } - - ~File() { - unlink(path_); - } - } file(address.sun_path); - - _syscall(bind(server, reinterpret_cast(&address), sizeof(address))); - _syscall(chmod(address.sun_path, 0777)); - - _syscall(listen(server, 1)); - const char *const argv[] = {address.sun_path, NULL}; - InjectLibrary(pid, 1, argv); - client_ = _syscall(accept(server, NULL, NULL)); - } -#else - client_ = -1; +#ifdef CY_ATTACH + if (remote_ == NULL && pid != _not(pid_t)) + remote_ = new CYInjectRemote(pid); #endif - if (client_ == -1 && host != NULL && port != NULL) { - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - hints.ai_flags = 0; - - struct addrinfo *infos; - _syscall(getaddrinfo(host, port, &hints, &infos)); + if (remote_ == NULL && host != NULL && port != NULL) + remote_ = new CYSocketRemote(host, port); - _assert(infos != NULL); try { - for (struct addrinfo *info(infos); info != NULL; info = info->ai_next) { - int client(_syscall(socket(info->ai_family, info->ai_socktype, info->ai_protocol))); try { - _syscall(connect(client, info->ai_addr, info->ai_addrlen)); - client_ = client; - break; - } catch (...) { - _syscall(close(client)); - throw; - } - } - } catch (...) { - freeaddrinfo(infos); - throw; - } - } + if (remote_ == NULL) + remote_ = new CYLocalRemote(); if (script == NULL && tty) Console(options); @@ -1173,7 +1153,7 @@ int Main(int argc, char * const argv[], char const * const envp[]) { if (compile) std::cout << code; else { - CYUTF8String json(Run(pool, client_, code)); + CYUTF8String json(Run(pool, code)); if (CYStartsWith(json, "throw ")) { CYLexerHighlight(json.data, json.size, std::cerr); std::cerr << std::endl;