1 /* Cycript - Optimizing JavaScript Compiler/Runtime
 
   2  * Copyright (C) 2009-2013  Jay Freeman (saurik)
 
   5 /* GNU General Public License, Version 3 {{{ */
 
   7  * Cycript is free software: you can redistribute it and/or modify
 
   8  * it under the terms of the GNU General Public License as published
 
   9  * by the Free Software Foundation, either version 3 of the License,
 
  10  * or (at your option) any later version.
 
  12  * Cycript is distributed in the hope that it will be useful, but
 
  13  * WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15  * GNU General Public License for more details.
 
  17  * You should have received a copy of the GNU General Public License
 
  18  * along with Cycript.  If not, see <http://www.gnu.org/licenses/>.
 
  22 #include "cycript.hpp"
 
  23 #include "JavaScript.hpp"
 
  25 #include "Pooling.hpp"
 
  28 #include "Cycript.tab.hh"
 
  30 #include <Foundation/Foundation.h>
 
  31 #include <apr_thread_proc.h>
 
  35 #include <sys/types.h>
 
  36 #include <sys/socket.h>
 
  37 #include <netinet/in.h>
 
  42     const char * volatile data_;
 
  45 // XXX: this is "tre lame"
 
  46 @interface CYClient_ : NSObject {
 
  49 - (void) execute:(NSValue *)value;
 
  53 @implementation CYClient_
 
  55 - (void) execute:(NSValue *)value {
 
  56     CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
 
  57     const char *data(execute->data_);
 
  58     execute->data_ = NULL;
 
  59     execute->data_ = CYExecute(execute->pool_, CYUTF8String(data));
 
  68     apr_thread_t *thread_;
 
  70     CYClient(int socket) :
 
  76         _syscall(close(socket_));
 
  80         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
  82         CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
 
  85         if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
 
  93             if (!CYRecvAll(socket_, &size, sizeof(size)))
 
  97             char *data(new(pool) char[size + 1]);
 
  98             if (!CYRecvAll(socket_, data, size))
 
 102             CYStream stream(data, data + size);
 
 103             CYDriver driver(stream);
 
 105             cy::parser parser(driver);
 
 108             if (parser.parse() != 0 || !driver.errors_.empty()) {
 
 112                 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
 
 115                 CYContext context(options);
 
 116                 driver.program_->Replace(context);
 
 117                 std::ostringstream str;
 
 118                 CYOutput out(str, options);
 
 119                 out << *driver.program_;
 
 120                 std::string code(str.str());
 
 121                 CYExecute_ execute = {pool, code.c_str()};
 
 122                 NSValue *value([NSValue valueWithPointer:&execute]);
 
 124                     [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
 
 126                     [client execute:value];
 
 127                 json = execute.data_;
 
 128                 size = json == NULL ? _not(size_t) : strlen(json);
 
 133             if (!CYSendAll(socket_, &size, sizeof(size)))
 
 136                 if (!CYSendAll(socket_, json, size))
 
 144 static void * APR_THREAD_FUNC OnClient(apr_thread_t *thread, void *data) {
 
 145     CYClient *client(reinterpret_cast<CYClient *>(data));
 
 151 extern "C" void CYHandleClient(apr_pool_t *pool, int socket) {
 
 152     CYClient *client(new(pool) CYClient(socket));
 
 153     apr_threadattr_t *attr;
 
 154     _aprcall(apr_threadattr_create(&attr, client->pool_));
 
 155     _aprcall(apr_thread_create(&client->thread_, attr, &OnClient, client, client->pool_));
 
 158 extern "C" void CYHandleServer(pid_t pid) {
 
 159     CYInitializeDynamic();
 
 161     int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); try {
 
 162         struct sockaddr_un address;
 
 163         memset(&address, 0, sizeof(address));
 
 164         address.sun_family = AF_UNIX;
 
 165         sprintf(address.sun_path, "/tmp/.s.cy.%u", pid);
 
 167         _syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
 
 170         apr_pool_create(&pool, NULL);
 
 172         CYHandleClient(pool, socket);
 
 173     } catch (const CYException &error) {
 
 175         fprintf(stderr, "%s\n", error.PoolCString(pool));