Beispiel #1
0
	const std::string& str(bool utf8)	// returns UTF-8 encoded buffer content
	{
#if defined(_WIN32) && !defined(XS_STRING_UTF8)
		if (utf8)
#endif
			_buffer_str.assign(_buffer, _wptr-_buffer);
#if defined(_WIN32) && !defined(XS_STRING_UTF8)
		else
			_buffer_str = get_utf8(_buffer, _wptr-_buffer);
#endif

		return _buffer_str;
	}
/**
	@brief Collect characters into a character string.
	@param parser Pointer to a Parser.
	@return Pointer to parser->str_buf if successful, or NULL upon error.

	Translate the usual escape sequences.  In particular, "\u" escapes a sequence of four
	hex characters; turn the hex into the corresponding UTF-8 byte sequence.

	Return the string we have built, without the enclosing quotation marks, in
	parser->str_buf.  In case of error, log an error message.
*/
static const char* get_string( Parser* parser ) {

	if( parser->str_buf )
		buffer_reset( parser->str_buf );
	else
		parser->str_buf = buffer_init( 64 );

	growing_buffer* gb = parser->str_buf;

	// Collect the characters.
	for( ;; ) {
		char c = parser_nextc( parser );
		if( '"' == c )
			break;
		else if( !c ) {
			report_error( parser, parser->buff[ parser->index - 1  ],
						  "Quoted string not terminated" );
			return NULL;
		} else if( '\\' == c ) {
			c = parser_nextc( parser );
			switch( c ) {
				case '"'  : OSRF_BUFFER_ADD_CHAR( gb, '"'  ); break;
				case '\\' : OSRF_BUFFER_ADD_CHAR( gb, '\\' ); break;
				case '/'  : OSRF_BUFFER_ADD_CHAR( gb, '/'  ); break;
				case 'b'  : OSRF_BUFFER_ADD_CHAR( gb, '\b' ); break;
				case 'f'  : OSRF_BUFFER_ADD_CHAR( gb, '\f' ); break;
				case 'n'  : OSRF_BUFFER_ADD_CHAR( gb, '\n' ); break;
				case 'r'  : OSRF_BUFFER_ADD_CHAR( gb, '\r' ); break;
				case 't'  : OSRF_BUFFER_ADD_CHAR( gb, '\t' ); break;
				case 'u'  : {
					Unibuff unibuff;
					if( get_utf8( parser, &unibuff ) ) {
						return NULL;       // bad UTF-8
					} else if( unibuff.buff[0] ) {
						OSRF_BUFFER_ADD( gb, (char*) unibuff.buff );
					} else {
						report_error( parser, 'u', "Unicode sequence encodes a nul byte" );
						return NULL;
					}
					break;
				}
				default   : OSRF_BUFFER_ADD_CHAR( gb, c );    break;
			}
		}
		else
			OSRF_BUFFER_ADD_CHAR( gb, c );
	}

	return OSRF_BUFFER_C_STR( gb );
}
Beispiel #3
0
static void parse_dive_cylinder(char *line, struct membuffer *str, void *_dive)
{
	struct dive *dive = _dive;
	cylinder_t *cylinder = dive->cylinder + cylinder_index;

	cylinder_index++;
	cylinder->type.description = get_utf8(str);
	for (;;) {
		char c;
		while (isspace(c = *line))
			line++;
		if (!c)
			break;
		line = parse_keyvalue_entry(parse_cylinder_keyvalue, cylinder, line);
	}
}
Beispiel #4
0
static void parse_dive_weightsystem(char *line, struct membuffer *str, void *_dive)
{
	struct dive *dive = _dive;
	weightsystem_t *ws = dive->weightsystem + weightsystem_index;

	weightsystem_index++;
	ws->description = get_utf8(str);
	for (;;) {
		char c;
		while (isspace(c = *line))
			line++;
		if (!c)
			break;
		line = parse_keyvalue_entry(parse_weightsystem_keyvalue, ws, line);
	}
}
Beispiel #5
0
static void parse_dive_location(char *line, struct membuffer *str, void *_dive)
{
	uint32_t uuid;
	char *name = get_utf8(str);
	struct dive *dive = _dive;
	struct dive_site *ds = get_dive_site_for_dive(dive);
	if (!ds) {
		uuid = get_dive_site_uuid_by_name(name, NULL);
		if (!uuid)
			uuid = create_dive_site(name, dive->when);
		dive->dive_site_uuid = uuid;
	} else {
		// we already had a dive site linked to the dive
		if (same_string(ds->name, "")) {
			ds->name = strdup(name);
		} else {
			// and that dive site had a name. that's weird - if our name is different, add it to the notes
			if (!same_string(ds->name, name))
				ds->notes = add_to_string(ds->notes, translate("gettextFromC", "additional name for site: %s\n"), name);
		}
	}
	free(name);
}
Beispiel #6
0
static void parse_dive_notes(char *line, struct membuffer *str, void *_dive)
{ struct dive *dive = _dive; dive->notes = get_utf8(str); }
Beispiel #7
0
static void parse_dive_suit(char *line, struct membuffer *str, void *_dive)
{ struct dive *dive = _dive; dive->suit = get_utf8(str); }
Beispiel #8
0
static void parse_dive_buddy(char *line, struct membuffer *str, void *_dive)
{ struct dive *dive = _dive; dive->buddy = get_utf8(str); }
Beispiel #9
0
static void parse_picture_filename(char *line, struct membuffer *str, void *_pic)
{
	struct picture *pic = _pic;
	pic->filename = get_utf8(str);
}
Beispiel #10
0
static void parse_trip_location(char *line, struct membuffer *str, void *_trip)
{ dive_trip_t *trip = _trip; trip->location = get_utf8(str); }
Beispiel #11
0
static void parse_picture_hash(char *line, struct membuffer *str, void *_pic)
{
	struct picture *pic = _pic;
	pic->hash = get_utf8(str);
}
Beispiel #12
0
 /// encode XML string literals
std::string EncodeXMLString(const XS_String& str, bool cdata)
{
	LPCXSSTR s = str.c_str();
	size_t l = XS_len(s);

	if (cdata) {
		 // encode the whole string in a CDATA section
		std::string ret = CDATA_START;

#ifdef XS_STRING_UTF8
		ret += str;
#else
		ret += get_utf8(str);
#endif

		ret += CDATA_END;

		return ret;
	} else if (l <= BUFFER_LEN) {
		LPXSSTR buffer = (LPXSSTR)alloca(6*sizeof(XS_CHAR)*XS_len(s));	// worst case "&quot;" / "&apos;"
		LPXSSTR o = buffer;

		for(LPCXSSTR p=s; *p; ++p)
			switch(*p) {
			  case '&':
				*o++ = '&';	*o++ = 'a';	*o++ = 'm';	*o++ = 'p';	*o++ = ';';				// "&amp;"
				break;

			  case '<':
				*o++ = '&';	*o++ = 'l'; *o++ = 't';	*o++ = ';';							// "&lt;"
				break;

			  case '>':
				*o++ = '&';	*o++ = 'g'; *o++ = 't';	*o++ = ';';							// "&gt;"
				break;

			  case '"':
				*o++ = '&';	*o++ = 'q'; *o++ = 'u'; *o++ = 'o'; *o++ = 't';	*o++ = ';';	// "&quot;"
				break;

			  case '\'':
				*o++ = '&';	*o++ = 'a'; *o++ = 'p'; *o++ = 'o'; *o++ = 's';	*o++ = ';';	// "&apos;"
				break;

			  default:
				if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n') {
					char b[16];
					sprintf(b, "&#%d;", (unsigned)*p);
					for(const char*q=b; *q; )
						*o++ = *q++;
				} else
					*o++ = *p;
			}

#ifdef XS_STRING_UTF8
		return XS_String(buffer, o-buffer);
#else
		return get_utf8(buffer, o-buffer);
#endif
	} else { // l > BUFFER_LEN
		 // alternative code for larger strings using ostringstream
		 // and avoiding to use alloca() for preallocated memory
		fast_ostringstream out;

		LPCXSSTR s = str.c_str();

		for(LPCXSSTR p=s; *p; ++p)
			switch(*p) {
			  case '&':
				out << "&amp;";
				break;

			  case '<':
				out << "&lt;";
				break;

			  case '>':
				out << "&gt;";
				break;

			  case '"':
				out << "&quot;";
				break;

			  case '\'':
				out << "&apos;";
				break;

			  default:
				if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n')
					out << "&#" << (unsigned)*p << ";";
				else
					out << *p;
			}

#ifdef XS_STRING_UTF8
		return XS_String(out.str());
#else
		return get_utf8(out.str());
#endif
	}
}
Beispiel #13
0
static Int rl_to_codes(Term TEnd, int do_as_binary, int arity USES_REGS) {
  int sno = Yap_CheckStream(ARG1, Input_Stream_f, "read_line_to_codes/2");
  StreamDesc *st = GLOBAL_Stream + sno;
  Int status;
  UInt max_inp, buf_sz, sz;
  unsigned char *buf;
  bool binary_stream;
  int ch;

  if (sno < 0)
    return false;
  status = GLOBAL_Stream[sno].status;
  binary_stream = GLOBAL_Stream[sno].status & Binary_Stream_f;
  if (status & Eof_Stream_f) {
    UNLOCK(GLOBAL_Stream[sno].streamlock);
    return Yap_unify_constant(ARG2, MkAtomTerm(AtomEof));
  }
  max_inp = (ASP - HR) / 2 - 1024;
  buf = (unsigned char *)TR;
  buf_sz = (unsigned char *)LOCAL_TrailTop - buf;
  while (true) {
    if (buf_sz > max_inp) {
      buf_sz = max_inp;
    }
    if (do_as_binary && !binary_stream) {
      GLOBAL_Stream[sno].status |= Binary_Stream_f;
    }
    if (st->status & Binary_Stream_f) {
      char *b = (char *)TR;
      sz = fread(b, 1, buf_sz, GLOBAL_Stream[sno].file);
    } else {
      unsigned char *pt = buf;
      do {
        ch = st->stream_wgetc_for_read(sno);
        if (ch < 127) {
          *pt++ = ch;
          if (ch < 0) {
              ch = '\n';
              pt[-1] = '\n';
         }
        } else {
            pt += get_utf8(pt, 4, &ch);
            if (pt + 4 == buf + buf_sz)
            break;
         }
      } while (ch != '\n');
      sz = pt - buf;
    }
    if (do_as_binary && !binary_stream)
      GLOBAL_Stream[sno].status &= ~Binary_Stream_f;
    if (sz == -1 || sz == 0) {
      if (GLOBAL_Stream[sno].status & Eof_Stream_f) {
        UNLOCK(GLOBAL_Stream[sno].streamlock);
        return Yap_unify_constant(ARG2, MkAtomTerm(AtomEof));
      }
      UNLOCK(GLOBAL_Stream[sno].streamlock);
    }
    if (GLOBAL_Stream[sno].status & Eof_Stream_f || buf[sz - 1] == 10) {
      /* we're done */
      Term end;
      if (!(do_as_binary || GLOBAL_Stream[sno].status & Eof_Stream_f)) {
        UNLOCK(GLOBAL_Stream[sno].streamlock);
        /* handle CR before NL */
        if ((Int)sz - 2 >= 0 && buf[sz - 2] == 13)
          buf[sz - 2] = '\0';
        else
          buf[sz - 1] = '\0';
      } else {
        UNLOCK(GLOBAL_Stream[sno].streamlock);
      }
      if (arity == 2)
        end = TermNil;
      else
        end = Deref(XREGS[arity]);
      return Yap_unify(
          ARG2, Yap_UTF8ToDiffListOfCodes((const char *)TR, end PASS_REGS));
     }
    buf += (buf_sz - 1);
    max_inp -= (buf_sz - 1);
    if (max_inp <= 0) {
      UNLOCK(GLOBAL_Stream[sno].streamlock);
      Yap_Error(RESOURCE_ERROR_STACK, ARG1, "read_line_to_codes/%d", arity);
      return FALSE;
    }
  }
}
Beispiel #14
0
static Int read_line_to_string(USES_REGS1) {
  int sno = Yap_CheckStream(ARG1, Input_Stream_f, "read_line_to_codes/2");
  Int status;
  UInt max_inp, buf_sz;
  unsigned char *buf;
  size_t sz;
  StreamDesc *st = GLOBAL_Stream + sno;
  int ch;

  if (sno < 0)
    return false;
  status = GLOBAL_Stream[sno].status;
  if (status & Eof_Stream_f) {
    UNLOCK(GLOBAL_Stream[sno].streamlock);
    return Yap_unify_constant(ARG2, MkAtomTerm(AtomEof));
  }
  max_inp = (ASP - HR) / 2 - 1024;
  buf = (unsigned char *)TR;
  buf_sz = (unsigned char *)LOCAL_TrailTop - buf;
 
    if (buf_sz > max_inp) {
      buf_sz = max_inp;
    }
    if (st->status & Binary_Stream_f) {
      char *b = (char *)TR;
      sz = fread(b, 1, buf_sz, GLOBAL_Stream[sno].file);
    } else {
      unsigned char *pt = buf;
      do {
         ch = st->stream_wgetc_for_read(sno);
        if (ch < 127) {
          *pt++ = ch;
          if (ch < 0) {
            ch = '\n';
            pt[-1] = '\n';
          }
        } else {
          pt += get_utf8(pt, 4, &ch);
          if (pt + 4 == buf + buf_sz)
            break;
        }
      } while (ch != '\n');
      sz = pt - buf;
    }
  if (sz == -1 || sz == 0) {
    if (GLOBAL_Stream[sno].status & Eof_Stream_f) {
      UNLOCK(GLOBAL_Stream[sno].streamlock);
      return Yap_unify_constant(ARG2, MkAtomTerm(AtomEof));
    }
    UNLOCK(GLOBAL_Stream[sno].streamlock);
    return false;
  }
  if (GLOBAL_Stream[sno].status & Eof_Stream_f || buf[sz - 1] == 10) {
    /* we're done */

    if (!(GLOBAL_Stream[sno].status & Eof_Stream_f)) {
      UNLOCK(GLOBAL_Stream[sno].streamlock);
      /* handle CR before NL */
      if ((Int)sz - 2 >= 0 && buf[sz - 2] == 13)
        buf[sz - 2] = '\0';
      else {
        buf[sz - 1] = '\0';
      }
    } else {
      UNLOCK(GLOBAL_Stream[sno].streamlock);
    }
  }
  if (GLOBAL_Stream[sno].encoding == ENC_ISO_UTF8) {
    return Yap_unify(ARG2, Yap_UTF8ToString((const char *)TR PASS_REGS));
  } else if (GLOBAL_Stream[sno].encoding == ENC_WCHAR) {
    return Yap_unify(ARG2, Yap_WCharsToString((const wchar_t *)TR PASS_REGS));
  } else {
    return Yap_unify(
        ARG2, Yap_CharsToString((const char *)TR, ENC_ISO_LATIN1 PASS_REGS));
  }
  buf += (buf_sz - 1);
  max_inp -= (buf_sz - 1);
  if (max_inp <= 0) {
    UNLOCK(GLOBAL_Stream[sno].streamlock);
    Yap_Error(RESOURCE_ERROR_STACK, ARG1, NULL);
    return FALSE;
  }
}
Beispiel #15
0
jboolean
Java_com_caucho_bootjni_JniProcess_exec(JNIEnv *env,
				     jobject obj,
				     jobjectArray j_argv,
				     jobjectArray j_envp,
				     jstring j_chroot,
				     jstring j_pwd,
				     jstring j_user,
				     jstring j_group)
{
  char **argv;
  char **envp;
  char chroot_path[4096];
  char pwd[4096];
  char user[256];
  char group[256];
  int uid = -1;
  int gid = -1;
  int len;
  int i;
  int pipe_fds[2];
  int pid;
  jclass c_jni_process;
  jfieldID f_stdoutFd;
  jfieldID f_pid;

#ifdef WIN32
  if (1) return -1;
#endif /* WIN32 */
  
  user[0] = 0;
  group[0] = 0;
  chroot_path[0] = 0;
  
  if (! j_argv) {
    resin_printf_exception(env, "java/lang/NullPointerException", "argv");
    return 0;
  }
  
  if (! j_envp) {
    resin_printf_exception(env, "java/lang/NullPointerException", "argv");
    return 0;
  }
  
  if (! j_pwd) {
    resin_printf_exception(env, "java/lang/NullPointerException", "pwd");
    return 0;
  }

  c_jni_process = (*env)->FindClass(env, "com/caucho/bootjni/JniProcess");

  if (! c_jni_process) {
    resin_printf_exception(env, "java/lang/NullPointerException", "can't load JniProcess");
    return 0;
  }

  f_stdoutFd = (*env)->GetFieldID(env, c_jni_process, "_stdoutFd", "I");

  if (! f_stdoutFd) {
    resin_printf_exception(env, "java/lang/NullPointerException", "can't load field");
    return 0;
  }

  f_pid = (*env)->GetFieldID(env, c_jni_process, "_pid", "I");

  if (! f_pid) {
    resin_printf_exception(env, "java/lang/NullPointerException", "can't load field");
    return 0;
  }

  len = (*env)->GetArrayLength(env, j_argv);
  argv = malloc((len + 1) * sizeof(char*));
  argv[len] = 0;
  
  for (i = 0; i < len; i++) {
    jstring j_string;

    j_string = (*env)->GetObjectArrayElement(env, j_argv, i);

    if (j_string) {
      int strlen = (*env)->GetStringUTFLength(env, j_string);
      
      argv[i] = (char *) malloc(strlen + 1);
    
      argv[i] = get_utf8(env, j_string, argv[i], strlen + 1);
    }
  }

  len = (*env)->GetArrayLength(env, j_envp);
  envp = malloc((len + 1) * sizeof(char*));
  envp[len] = 0;
  
  for (i = 0; i < len; i++) {
    jstring j_string;

    j_string = (*env)->GetObjectArrayElement(env, j_envp, i);

    if (j_string) {
      int strlen = (*env)->GetStringUTFLength(env, j_string);
      
      envp[i] = (char *) malloc(strlen + 1);
    
      envp[i] = get_utf8(env, j_string, envp[i], strlen + 1);
    }
  }

  if (j_chroot) {
    int strlen = (*env)->GetStringUTFLength(env, j_chroot);

    get_utf8(env, j_chroot, chroot_path, strlen + 1);
  }
  else
    chroot_path[0] = 0;

  if (j_pwd) {
    int strlen = (*env)->GetStringUTFLength(env, j_pwd);

    get_utf8(env, j_pwd, pwd, strlen + 1);
  }

#ifndef WIN32
  if (j_user) {
    struct passwd *passwd;
    int strlen = (*env)->GetStringUTFLength(env, j_user);

    get_utf8(env, j_user, user, strlen + 1);

    passwd = getpwnam(user);

    if (! passwd) {
      resin_printf_exception(env, "java/lang/IllegalArgumentException",
			     "%s is an unknown user", user);
      return 0;
    }
    
    uid = passwd->pw_uid;
    gid = passwd->pw_gid;
  }
  
  if (j_group) {
    struct group *group_ent;
    int strlen = (*env)->GetStringUTFLength(env, j_group);

    get_utf8(env, j_group, group, strlen + 1);

    group_ent = getgrnam(group);

    if (! group_ent) {
      resin_printf_exception(env, "java/lang/IllegalArgumentException",
			     "%s is an unknown group", group);
      return 0;
    }
    
    gid = group_ent->gr_gid;
  }
  
  pipe(pipe_fds);

  pid = fork();

  if (pid > 0) {
    close(pipe_fds[1]);

    (*env)->SetIntField(env, obj, f_stdoutFd, pipe_fds[0]);
    (*env)->SetIntField(env, obj, f_pid, pid);
    
    return 1;
  }
  else if (pid < 0) {
    close(pipe_fds[0]);
    close(pipe_fds[1]);
    
    resin_printf_exception(env, "java/lang/NullPointerException",
			   "can't fork");
    return 0;
  }

  close(pipe_fds[0]);

  /*
  if (fork())
    exit(0);
  
  setsid();
  */

#ifndef WIN32  
  if (chroot_path[0]) {
    chroot(chroot_path);
  }
#endif

  if (gid >= 0)
    setregid(gid, gid);
  
  if (uid >= 0) {
    setreuid(uid, uid);

    if (getuid() != uid) {
      fprintf(stderr, "Can't setuid to %d, received %d\n", uid, getuid());
      exit(1);
    }
  }
  
  chdir(pwd);
#endif

  dup2(pipe_fds[1], 1);
  dup2(pipe_fds[1], 2);

  for (i = 0; envp[i]; i++)
    putenv(envp[i]);

  execvp(argv[0], argv);

  fprintf(stderr, "exec failed %s -> %d\n", argv[0], errno);
  exit(1);
  
  return -1;
}
Beispiel #16
0
static void parse_dc_model(char *line, struct membuffer *str, void *_dc)
{ struct divecomputer *dc = _dc; dc->model = get_utf8(str); }
Beispiel #17
0
static void parse_dive_location(char *line, struct membuffer *str, void *_dive)
{ struct dive *dive = _dive; dive->location = get_utf8(str); }
Beispiel #18
0
static void parse_trip_notes(char *line, struct membuffer *str, void *_trip)
{ dive_trip_t *trip = _trip; trip->notes = get_utf8(str); }
Beispiel #19
0
static void parse_dive_divemaster(char *line, struct membuffer *str, void *_dive)
{ struct dive *dive = _dive; dive->divemaster = get_utf8(str); }
Beispiel #20
0
/* input line with encoding conversion */
long input_line2(FILE *fp, unsigned char *buff, long pos,
                 const long buffsize, int *lastchar)
{
    long i;
    static boolean injis = false;
    const int fd = fileno(fp);

    if (infile_enc[fd] == ENC_UNKNOWN) { /* just after opened */
        ungetbuff[fd].size = 0;
        if (isUTF8Nstream(fp)) infile_enc[fd] = ENC_UTF8;
        else                   infile_enc[fd] = get_file_enc();
    }
    buffer = buff;
    first = last = pos;

    while (last < buffsize-30 && (i=getc4(fp)) != EOF && i!='\n' && i!='\r') {
        /* 30 is enough large size for one char */
        /* attention: 4 times of write_hex() eats 16byte */
#ifdef WIN32
        if (i == 0x1a && first == last &&
            fd == fileno(stdin) && _isatty(fd)) { /* Ctrl+Z on console */
                i = EOF;
                break;
        } else
#endif
        if (i == ESC) {
            if ((i=getc4(fp)) == '$') { /* ESC '$' (Kanji-in) */
                i = getc4(fp);
                if (i == '@' || i == 'B') {
                    injis = true;
                } else {               /* broken Kanji-in */
                    buffer[last++] = ESC;
                    buffer[last++] = '$';
                    if (is_tail(&i, fp)) break;
                    buffer[last++] = i;
                }
            } else if (i == '(') {     /* ESC '(' (Kanji-out) */
                i = getc4(fp);
                if (i == 'J' || i == 'B' || i == 'H') {
                    injis = false;
                } else {               /* broken Kanji-out */
                    buffer[last++] = ESC;
                    buffer[last++] = '(';
                    if (is_tail(&i, fp)) break;
                    buffer[last++] = i;
                }
            } else { /* broken ESC */
                buffer[last++] = ESC;
                if (is_tail(&i, fp)) break;
                buffer[last++] = i;
            }
        } else { /* rather than ESC */
            if (injis) { /* in JIS */
                long j = getc4(fp);
                if (is_tail(&j, fp)) {
                    buffer[last++] = i;
                    i = j;
                    break;
                } else { /* JIS encoding */
                    i = fromJIS(HILO(i,j));
                    if (i == 0) i = fromUCS(U_REPLACEMENT_CHARACTER);
                    write_multibyte(toBUFF(i));
                }
            } else {  /* normal */
                if        (infile_enc[fd] == ENC_SJIS && isSJISkanji1(i)) {
                    get_sjis(i, fp);
                } else if (infile_enc[fd] == ENC_EUC  && isEUCkanji1(i)) {
                    get_euc(i, fp);
                } else if (infile_enc[fd] == ENC_UTF8 && UTF8length(i) > 1) {
                    get_utf8(i, fp);
                } else {
                    buffer[last++] = i;
                }
            }
        }
    }

    buffer[last] = '\0';
    if (i == EOF || i == '\n' || i == '\r') injis = false;
    if (lastchar != NULL) *lastchar = i;

    return last;
}
Beispiel #21
0
JNIEXPORT jint JNICALL
Java_com_caucho_server_boot_ResinBoot_execDaemon(JNIEnv *env,
        jobject obj,
        jobjectArray j_argv,
        jobjectArray j_envp,
        jstring j_pwd)
{
    char **argv;
    char **envp;
    char *pwd;
    int len;
    int i;

    if (! j_argv)
        resin_printf_exception(env, "java/lang/NullPointerException", "argv");
    if (! j_envp)
        resin_printf_exception(env, "java/lang/NullPointerException", "argv");
    if (! j_pwd)
        resin_printf_exception(env, "java/lang/NullPointerException", "pwd");

#ifdef WIN32
    resin_printf_exception(env, "java/lang/UnsupportedOperationException", "win32");
#else
    len = (*env)->GetArrayLength(env, j_argv);
    argv = malloc((len + 1) * sizeof(char*));
    argv[len] = 0;

    for (i = 0; i < len; i++) {
        jstring j_string;

        j_string = (*env)->GetObjectArrayElement(env, j_argv, i);

        if (j_string) {
            int strlen = (*env)->GetStringUTFLength(env, j_string);

            argv[i] = (char *) malloc(strlen + 1);

            argv[i] = get_utf8(env, j_string, argv[i], strlen + 1);
        }
    }

    len = (*env)->GetArrayLength(env, j_envp);
    envp = malloc((len + 1) * sizeof(char*));
    envp[len] = 0;

    for (i = 0; i < len; i++) {
        jstring j_string;

        j_string = (*env)->GetObjectArrayElement(env, j_envp, i);

        if (j_string) {
            int strlen = (*env)->GetStringUTFLength(env, j_string);

            envp[i] = (char *) malloc(strlen + 1);

            envp[i] = get_utf8(env, j_string, envp[i], strlen + 1);
        }
    }

    {
        int strlen = (*env)->GetStringUTFLength(env, j_pwd);
        char *pwd;

        pwd = (char *) malloc(strlen + 1);
        pwd = get_utf8(env, j_pwd, pwd, strlen + 1);

        chdir(pwd);
    }

    if (fork())
        return 1;

    if (fork())
        exit(0);

#ifndef WIN32
    setsid();
#endif /* WIN32 */

    execve(argv[0], argv, envp);

    fprintf(stderr, "exec failed %s -> %d\n", argv[0], errno);
    exit(1);
#endif
    return -1;
}