1 /* Cycript - Inlining/Optimizing JavaScript Compiler
 
   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.
 
  40 #include "cycript.hpp"
 
  41 #include "JavaScript.hpp"
 
  43 #include "Pooling.hpp"
 
  46 #include "Cycript.tab.hh"
 
  48 #include <Foundation/Foundation.h>
 
  49 #include <apr_thread_proc.h>
 
  53 #include <sys/types.h>
 
  54 #include <sys/socket.h>
 
  55 #include <netinet/in.h>
 
  60     const char * volatile data_;
 
  63 // XXX: this is "tre lame"
 
  64 @interface CYClient_ : NSObject {
 
  67 - (void) execute:(NSValue *)value;
 
  71 @implementation CYClient_
 
  73 - (void) execute:(NSValue *)value {
 
  74     CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
 
  75     const char *data(execute->data_);
 
  76     execute->data_ = NULL;
 
  77     execute->data_ = CYExecute(execute->pool_, CYUTF8String(data));
 
  86     apr_thread_t *thread_;
 
  88     CYClient(int socket) :
 
  94         _syscall(close(socket_));
 
  98         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
 100         CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
 
 103         if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
 
 111             if (!CYRecvAll(socket_, &size, sizeof(size)))
 
 115             char *data(new(pool) char[size + 1]);
 
 116             if (!CYRecvAll(socket_, data, size))
 
 121             cy::parser parser(driver);
 
 127             if (parser.parse() != 0 || !driver.errors_.empty()) {
 
 131                 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
 
 134                 CYContext context(options);
 
 135                 driver.program_->Replace(context);
 
 136                 std::ostringstream str;
 
 137                 CYOutput out(str, options);
 
 138                 out << *driver.program_;
 
 139                 std::string code(str.str());
 
 140                 CYExecute_ execute = {pool, code.c_str()};
 
 141                 NSValue *value([NSValue valueWithPointer:&execute]);
 
 143                     [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
 
 145                     [client execute:value];
 
 146                 json = execute.data_;
 
 147                 size = json == NULL ? _not(size_t) : strlen(json);
 
 152             if (!CYSendAll(socket_, &size, sizeof(size)))
 
 155                 if (!CYSendAll(socket_, json, size))
 
 163 static void * APR_THREAD_FUNC OnClient(apr_thread_t *thread, void *data) {
 
 164     CYClient *client(reinterpret_cast<CYClient *>(data));
 
 170 extern "C" void CYHandleClient(apr_pool_t *pool, int socket) {
 
 171     CYClient *client(new(pool) CYClient(socket));
 
 172     apr_threadattr_t *attr;
 
 173     _aprcall(apr_threadattr_create(&attr, client->pool_));
 
 174     _aprcall(apr_thread_create(&client->thread_, attr, &OnClient, client, client->pool_));
 
 177 extern "C" void CYHandleServer(pid_t pid) {
 
 178     CYInitializeDynamic();
 
 180     int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); try {
 
 181         struct sockaddr_un address;
 
 182         memset(&address, 0, sizeof(address));
 
 183         address.sun_family = AF_UNIX;
 
 184         sprintf(address.sun_path, "/tmp/.s.cy.%u", pid);
 
 186         _syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
 
 189         apr_pool_create(&pool, NULL);
 
 191         CYHandleClient(pool, socket);
 
 192     } catch (const CYException &error) {
 
 194         fprintf(stderr, "%s\n", error.PoolCString(pool));