]>
git.saurik.com Git - cycript.git/blob - Console.cpp
d938217b353dd33797902784b70c3b28a96db8e8
   1 /* Cycript - Remove Execution Server and Disassembler 
   2  * Copyright (C) 2009  Jay Freeman (saurik) 
   5 /* Modified BSD License {{{ */ 
   7  *        Redistribution and use in source and binary 
   8  * forms, with or without modification, are permitted 
   9  * provided that the following conditions are met: 
  11  * 1. Redistributions of source code must retain the 
  12  *    above copyright notice, this list of conditions 
  13  *    and the following disclaimer. 
  14  * 2. Redistributions in binary form must reproduce the 
  15  *    above copyright notice, this list of conditions 
  16  *    and the following disclaimer in the documentation 
  17  *    and/or other materials provided with the 
  19  * 3. The name of the author may not be used to endorse 
  20  *    or promote products derived from this software 
  21  *    without specific prior written permission. 
  23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' 
  24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  25  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 
  28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
  34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  42 #include <substrate.h> 
  43 #include "cycript.hpp" 
  50 #include <readline/readline.h> 
  51 #include <readline/history.h> 
  58 #include <sys/types.h> 
  62 #include "Cycript.tab.hh" 
  64 #include <sys/types.h> 
  65 #include <sys/socket.h> 
  66 #include <netinet/in.h> 
  69 static jmp_buf ctrlc_
; 
  71 static void sigint(int) { 
  75 void Run(int socket
, const char *data
, size_t size
, FILE *fout 
= NULL
, bool expand 
= false) { 
  80         json 
= CYExecute(pool
, data
); 
  84         CYSendAll(socket
, &size
, sizeof(size
)); 
  85         CYSendAll(socket
, data
, size
); 
  86         CYRecvAll(socket
, &size
, sizeof(size
)); 
  87         if (size 
== _not(size_t)) 
  90             char *temp(new(pool
) char[size 
+ 1]); 
  91             CYRecvAll(socket
, temp
, size
); 
  97     if (json 
!= NULL 
&& fout 
!= NULL
) { 
  98         if (!expand 
|| json
[0] != '"' && json
[0] != '\'') 
 100         else for (size_t i(0); i 
!= size
; ++i
) 
 102                 fputc(json
[i
], fout
); 
 103             else switch(json
[++i
]) { 
 104                 case '\0': goto done
; 
 105                 case '\\': fputc('\\', fout
); break; 
 106                 case '\'': fputc('\'', fout
); break; 
 107                 case '"': fputc('"', fout
); break; 
 108                 case 'b': fputc('\b', fout
); break; 
 109                 case 'f': fputc('\f', fout
); break; 
 110                 case 'n': fputc('\n', fout
); break; 
 111                 case 'r': fputc('\r', fout
); break; 
 112                 case 't': fputc('\t', fout
); break; 
 113                 case 'v': fputc('\v', fout
); break; 
 114                 default: fputc('\\', fout
); --i
; break; 
 123 void Run(int socket
, std::string 
&code
, FILE *fout 
= NULL
, bool expand 
= false) { 
 124     Run(socket
, code
.c_str(), code
.size(), fout
, expand
); 
 127 static void Console(int socket
) { 
 134     rl_bind_key('\t', rl_insert
); 
 136     struct sigaction action
; 
 137     sigemptyset(&action
.sa_mask
); 
 138     action
.sa_handler 
= &sigint
; 
 140     sigaction(SIGINT
, &action
, NULL
); 
 144         std::vector
<std::string
> lines
; 
 147         const char *prompt("cy# "); 
 149         if (setjmp(ctrlc_
) != 0) { 
 156         char *line(readline(prompt
)); 
 162             if (line
[0] == '?') { 
 163                 std::string 
data(line 
+ 1); 
 164                 if (data 
== "bypass") { 
 166                     fprintf(fout
, "bypass == %s\n", bypass 
? "true" : "false"); 
 168                 } else if (data 
== "debug") { 
 170                     fprintf(fout
, "debug == %s\n", debug 
? "true" : "false"); 
 172                 } else if (data 
== "expand") { 
 174                     fprintf(fout
, "expand == %s\n", expand 
? "true" : "false"); 
 183         for (char *state
, *token(apr_strtok(line
, "\n", &state
)); token 
!= NULL
; token 
= apr_strtok(NULL
, "\n", &state
)) 
 184             lines
.push_back(token
); 
 193             cy::parser 
parser(driver
); 
 195             driver
.data_ 
= command
.c_str(); 
 196             driver
.size_ 
= command
.size(); 
 198             if (parser
.parse() != 0 || !driver
.errors_
.empty()) { 
 199                 for (CYDriver::Errors::const_iterator 
error(driver
.errors_
.begin()); error 
!= driver
.errors_
.end(); ++error
) { 
 200                     cy::position 
begin(error
->location_
.begin
); 
 201                     if (begin
.line 
!= lines
.size() || begin
.column 
- 1 != lines
.back().size()) { 
 202                         cy::position 
end(error
->location_
.end
); 
 204                         if (begin
.line 
!= lines
.size()) { 
 206                             std::cerr 
<< lines
[begin
.line 
- 1] << std::endl
; 
 210                         for (size_t i(0); i 
!= begin
.column 
- 1; ++i
) 
 212                         if (begin
.line 
!= end
.line 
|| begin
.column 
== end
.column
) 
 214                         else for (size_t i(0), e(end
.column 
- begin
.column
); i 
!= e
; ++i
) 
 216                         std::cerr 
<< std::endl
; 
 219                         std::cerr 
<< error
->message_ 
<< std::endl
; 
 221                         add_history(command
.c_str()); 
 226                 driver
.errors_
.clear(); 
 233             if (driver
.source_ 
== NULL
) 
 239                 std::ostringstream str
; 
 240                 driver
.source_
->Show(str
); 
 245         add_history(command
.c_str()); 
 248             std::cout 
<< code 
<< std::endl
; 
 250         Run(socket
, code
, fout
, expand
); 
 257 static void *Map(const char *path
, size_t *psize
) { 
 259     _syscall(fd 
= open(path
, O_RDONLY
)); 
 262     _syscall(fstat(fd
, &stat
)); 
 263     size_t size(stat
.st_size
); 
 268     _syscall(base 
= mmap(NULL
, size
, PROT_READ
, MAP_SHARED
, fd
, 0)); 
 274 int main(int argc
, char *argv
[]) { 
 275     bool tty(isatty(STDIN_FILENO
)); 
 276     pid_t 
pid(_not(pid_t
)); 
 278     for (;;) switch (getopt(argc
, argv
, "p:")) { 
 282             fprintf(stderr
, "usage: cycript [-p <pid>] [<script> [<arg>...]]\n"); 
 286             size_t size(strlen(optarg
)); 
 288             pid 
= strtoul(optarg
, &end
, 0); 
 289             if (optarg 
+ size 
!= end
) { 
 290                 fprintf(stderr
, "invalid pid for -p\n"); 
 298     if (optind 
< argc 
- 1 && pid 
!= _not(pid_t
)) { 
 299         fprintf(stderr
, "-p cannot set argv\n"); 
 306         // XXX: const_cast?! wtf gcc :( 
 307         CYSetArgs(argc 
- optind 
- 1, const_cast<const char **>(argv 
+ optind 
+ 1)); 
 308         script 
= argv
[optind
]; 
 309         if (strcmp(script
, "-") == 0) 
 313     if (script 
== NULL 
&& !tty 
&& pid 
!= _not(pid_t
)) { 
 314         fprintf(stderr
, "non-terminal attaching to remove console\n"); 
 320     if (pid 
== _not(pid_t
)) 
 323         socket 
= _syscall(::socket(PF_UNIX
, SOCK_STREAM
, 0)); 
 325         struct sockaddr_un address
; 
 326         memset(&address
, 0, sizeof(address
)); 
 327         address
.sun_family 
= AF_UNIX
; 
 328         sprintf(address
.sun_path
, "/tmp/.s.cy.%u", pid
); 
 330         _syscall(connect(socket
, reinterpret_cast<sockaddr 
*>(&address
), SUN_LEN(&address
))); 
 333     if (script 
== NULL 
&& tty
) 
 336         CYDriver 
driver(script 
?: "<stdin>"); 
 337         cy::parser 
parser(driver
); 
 341         if (script 
== NULL
) { 
 345             driver
.file_ 
= stdin
; 
 348             start 
= reinterpret_cast<char *>(Map(script
, &size
)); 
 351             if (size 
>= 2 && start
[0] == '#' && start
[1] == '!') { 
 354                 if (void *line 
= memchr(start
, '\n', end 
- start
)) 
 355                     start 
= reinterpret_cast<char *>(line
); 
 360             driver
.data_ 
= start
; 
 361             driver
.size_ 
= end 
- start
; 
 364         if (parser
.parse() != 0 || !driver
.errors_
.empty()) { 
 365             for (CYDriver::Errors::const_iterator 
i(driver
.errors_
.begin()); i 
!= driver
.errors_
.end(); ++i
) 
 366                 std::cerr 
<< i
->location_
.begin 
<< ": " << i
->message_ 
<< std::endl
; 
 367         } else if (driver
.source_ 
!= NULL
) 
 369                 Run(socket
, start
, end 
- start
, stdout
); 
 371                 std::ostringstream str
; 
 372                 driver
.source_
->Show(str
); 
 373                 std::string 
code(str
.str());