void TransportManager::StartDebugger()

in modules/jpda/src/main/native/jdwp/unix/agent/core/TransportManager_pd.cpp [43:136]


void TransportManager::StartDebugger(const char* command, int extra_argc, const char* extra_argv[]) throw(AgentException)
{
    JDWP_TRACE_ENTRY("StartDebugger(" << JDWP_CHECK_NULL(command) << ',' << extra_argc << ',' << extra_argv << ')');

    // allocate array for parsed arguments

    int max_argc = 250 + extra_argc;
    char** argv = static_cast<char**>(GetMemoryManager().Allocate((sizeof(char*) * (max_argc + 1)) JDWP_FILE_LINE));
    AgentAutoFree afva(argv JDWP_FILE_LINE);

    // parse command line
    int argc = 0;        
    int cmd_len = strlen(command);
    char* cmd = static_cast<char*>(GetMemoryManager().Allocate((cmd_len + 1) JDWP_FILE_LINE));
    AgentAutoFree afv(cmd JDWP_FILE_LINE);

    if (command != 0 && cmd_len > 0) {
        JDWP_TRACE_PROG("StartDebugger: parse: cmd=" << JDWP_CHECK_NULL(command));

        const char *arg = command, *p;
        char *arg1 = cmd, *s;

        for (; *arg != 0;) {

            // skip initial spaces
            while (isspace(*arg)) arg++;

            // parse non-spaced or quoted argument 
            for (p = arg, s = arg1; ; p++) {
                // check for quote
                if (*p == '\"' || *p == '\'') {
                     char quote = *(p++);
                     // skip all chars until terminating quote or null
                     for (; *p != '\0'; p++) {
                         // check for terminating quote
                         if (*p == quote) {
                             p++;
                             break;
                         }
                         // preserve escaped quote
                         if (*p == '\\' && *(p + 1) == quote) 
                             p++;
                         // store current char
                         *(s++) = *p;
                     }
                }
                // check for ending separator
                if (*p == '\0' || isspace(*p)) {
                     *(s++) = '\0';
                     if (argc >= max_argc) {
                        JDWP_ERROR("Too many arguments for launching debugger proccess: " << argc);
                        throw AgentException(JDWP_ERROR_INTERNAL);
                     }
                     argv[argc++] = arg1;
                     JDWP_TRACE_PROG("StartDebugger: launch: arg[" << argc << "]=" << JDWP_CHECK_NULL(arg1));
                     arg = p;
                     arg1 = s;
                     break;
                }
                // skip escaped quote
                if (*p == '\\' && (*(p + 1) == '\"' || *(p + 1) == '\'')) 
                    p++;
                // store current char
                *(s++) = *p;
            }
        }
    }

    // add extra arguments

    int i;
    for (i = 0; i < extra_argc; i++) {
         if (extra_argv[i] != 0) {
             JDWP_TRACE_PROG("StartDebugger: launch: arg[" << argc << "]=" << JDWP_CHECK_NULL(extra_argv[i]));
             argv[argc++] = const_cast<char*>(extra_argv[i]);
         }
    }
    argv[argc] = 0;
    
    // launch debugger process

    int pid = fork();
    if (pid == -1) {
        JDWP_ERROR("Failed to fork debugger process: error=" << errno);
        throw AgentException(JDWP_ERROR_INTERNAL);
    } else if (pid == 0) {
        // execute debugger in child process
        execv(argv[0], argv);
        // returned here only in case of error, terminate child process
        JDWP_DIE("Failed to execute debugger process: error=" << errno);
    } else {
        JDWP_TRACE_PROG("StartDebugger: launched: pid=" << pid);
    }
}