/*
 * Add a class to the prepared class hash table.
 * Assumes no duplicates.
 */
void
classTrack_addPreparedClass(JNIEnv *env, jclass klass)
{
    jint slot = hashKlass(klass);
    KlassNode **head = &table[slot];
    KlassNode *node;

    if (assertOn) {
        /* Check this is not a duplicate */
        for (node = *head; node != NULL; node = node->next) {
            if ((*env)->IsSameObject(env, klass, node->klass)) {
                JDI_ASSERT_FAILED("Attempting to insert duplicate class");
                break;
            }
        }
    }
       
    node = jdwpAlloc(sizeof(KlassNode));
    if (node == NULL) {
        ALLOC_ERROR_EXIT();
    }
    if ((node->signature = classSignature(klass)) == NULL) {
        jdwpFree(node);
        ALLOC_ERROR_EXIT();
    }
    if ((node->klass = (*env)->NewWeakGlobalRef(env, klass)) == NULL) {
        jdwpFree(node->signature);
        jdwpFree(node);
        ALLOC_ERROR_EXIT();
    }

    /* Insert the new node */
    node->next = *head;
    *head = node;
}
static jint 
writeBytes(PacketOutputStream *stream, void *source, int size)
{
    jbyte *bytes = (jbyte *)source;

    if (stream->error) {
        return stream->error;
    }
    while (size > 0) {
        jint count;
        if (stream->left == 0) {
            jint segSize = MIN(2 * stream->segment->length, MAX_SEGMENT_SIZE);
            jbyte *newSeg = jdwpAlloc(segSize);
            struct PacketData *newHeader = jdwpAlloc(sizeof(*newHeader));
            if ((newSeg == NULL) || (newHeader == NULL)) {
                jdwpFree(newSeg);
                jdwpFree(newHeader);
                stream->error = JVMDI_ERROR_OUT_OF_MEMORY;
                return stream->error;
            }
            newHeader->length = 0;
            newHeader->data = newSeg;
            newHeader->next = NULL;
            stream->segment->next = newHeader;
            stream->segment = newHeader;
            stream->current = newHeader->data;
            stream->left = segSize;
        }
        count = MIN(size, stream->left);
        memcpy(stream->current, bytes, count);
        stream->current += count;
        stream->left -= count;
        stream->segment->length += count;
        size -= count;
        bytes += count;
    }
    return JVMDI_ERROR_NONE;
}
int 
dbgsysExec(char *cmdLine)
{
    int i;
    int argc;
    int pid = -1; /* this is the error return value */
    char **argv = NULL;
    char *p;
    char *args;

    /* Skip leading whitespace */
    cmdLine = skipWhitespace(cmdLine);

    args = jdwpAlloc(strlen(cmdLine)+1);
    if (args == NULL) {
        return SYS_NOMEM;
    }
    strcpy(args, cmdLine);

    p = args;

    argc = 0;
    while (*p != '\0') {
        p = skipNonWhitespace(p);
        argc++;
        if (*p == '\0') {
            break;
        }
        p = skipWhitespace(p);
    }

    argv = jdwpAlloc((argc + 1) * sizeof(char *));
    if (argv == 0) {
        jdwpFree(args);
        return SYS_NOMEM;
    }

    for (i = 0, p = args; i < argc; i++) {
        argv[i] = p;
        p = skipNonWhitespace(p);
        *p++ = '\0';
        p = skipWhitespace(p);
    }

    if ((pid = fork()) == 0) {
        /* Child process */
        int i, max_fd;

        /* close everything */
        max_fd = sysconf(_SC_OPEN_MAX);
        for (i = 3; i < max_fd; i++) {
            close(i);
        }

        execvp(argv[0], argv);

        exit(-1);
    }
    jdwpFree(args);
    jdwpFree(argv);
    if (pid < 0) {
        return SYS_ERR;
    } else {
        return SYS_OK;
    }
}