Пример #1
0
/* All normal exit doors lead here */
void
debugInit_exit(jvmtiError error, const char *msg)
{
    enum exit_codes { EXIT_NO_ERRORS = 0, EXIT_JVMTI_ERROR = 1, EXIT_TRANSPORT_ERROR = 2 };

    // Prepare to exit. Log error and finish logging
    LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error,
              ((msg == NULL) ? "" : msg)));

    // coredump requested by command line. Keep JVMTI data dirty
    if (error != JVMTI_ERROR_NONE && docoredump) {
        LOG_MISC(("Dumping core as requested by command line"));
        finish_logging();
        abort();
    }

    finish_logging();

    // Cleanup the JVMTI if we have one
    if (gdata != NULL) {
        gdata->vmDead = JNI_TRUE;
        if (gdata->jvmti != NULL) {
            // Dispose of jvmti (gdata->jvmti becomes NULL)
            disposeEnvironment(gdata->jvmti);
        }
    }

    // We are here with no errors. Kill entire process and exit with zero exit code
    if (error == JVMTI_ERROR_NONE) {
        forceExit(EXIT_NO_ERRORS);
        return;
    }

    // No transport initilized.
    // As we don't have any details here exiting with separate exit code
    if (error == AGENT_ERROR_TRANSPORT_INIT) {
        forceExit(EXIT_TRANSPORT_ERROR);
        return;
    }

    // We have JVMTI error. Call hotspot jni_FatalError handler
    jniFatalError(NULL, msg, error, EXIT_JVMTI_ERROR);

    // hotspot calls os:abort() so we should never reach code below,
    // but guard against possible hotspot changes

    // Last chance to die, this kills the entire process.
    forceExit(EXIT_JVMTI_ERROR);
}
Пример #2
0
/* All JVM fatal error exits lead here (e.g. we need to kill the VM). */
static void
jniFatalError(JNIEnv *env, const char *msg, jvmtiError error, int exit_code)
{
    JavaVM *vm;
    char buf[512];

    gdata->vmDead = JNI_TRUE;
    if ( msg==NULL )
        msg = "UNKNOWN REASON";
    vm = gdata->jvm;
    if ( env==NULL && vm!=NULL ) {
        jint rc = (*((*vm)->GetEnv))(vm, (void **)&env, JNI_VERSION_1_2);
        if (rc != JNI_OK ) {
            env = NULL;
        }
    }
    if ( error != JVMTI_ERROR_NONE ) {
        (void)snprintf(buf, sizeof(buf), "JDWP %s, jvmtiError=%s(%d)",
                       msg, jvmtiErrorText(error), error);
    } else {
        (void)snprintf(buf, sizeof(buf), "JDWP %s", buf);
    }
    if (env != NULL) {
        (*((*env)->FatalError))(env, buf);
    } else {
        /* Should rarely ever reach here, means VM is really dead */
        print_message(stderr, "ERROR: JDWP: ", "\n",
                      "Can't call JNI FatalError(NULL, \"%s\")", buf);
    }
    forceExit(exit_code);
}
Пример #3
0
void getLocal(const char *device)
{
    /* get local IPv4 addresses */
    int sock;
    struct ifreq iFreq;
    //iFreq用来保存某个接口的信息
    //--http://blog.csdn.net/vc0051127833/article/details/7029556
    struct sockaddr_in *saddr;
    if ((sock = socket(AF_INET, SOCK_RAW, htons(0x0806))) < 0)
    {
        forceExit("creating socket failed while establishing local IP - are you root?");
    }
    strcpy(iFreq.ifr_name, device); //把网卡(device)的名字复制到iFreq的name变量
    if (ioctl(sock, SIOCGIFADDR, &iFreq) < 0)
    { //获取接口地址,0->成功,-1->出错,改变iFreq,记录网卡的信息
        //--http://www.iteye.com/topic/309442
        forceExit("ioctl failed while establishing local IP for selected device %s. You may specify the device on the command line.");
    }
    saddr = (struct sockaddr_in*) &iFreq.ifr_addr;
    local_addrs = new local_addr(saddr->sin_addr.s_addr);
}
Пример #4
0
/**
 * @returns the username that corresponds to this uid 
 */
std::string uid2username (uid_t uid)
{
	struct passwd * pwd = NULL;
	errno = NULL;

	/* points to a static memory area, should not be freed */
	pwd = getpwuid(uid);

	if (pwd == NULL)
		if (errno == 0)
			return itoa(uid);
		else
			forceExit(false, "Error calling getpwuid(3) for uid %d: %d %s", uid, errno, strerror(errno));
	else
		return std::string(pwd->pw_name);
}
Пример #5
0
/* All normal exit doors lead here */
void
debugInit_exit(jvmtiError error, const char *msg)
{
    int exit_code = 0;

    /* Pick an error code */
    if ( error != JVMTI_ERROR_NONE ) {
        exit_code = 1;
        if ( docoredump ) {
            finish_logging(exit_code);
            abort();
        }
    }
    if ( msg==NULL ) {
        msg = "";
    }

    LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, msg));

    gdata->vmDead = JNI_TRUE;

    /* Let's try and cleanup the JVMTI, if we even have one */
    if ( gdata->jvmti != NULL ) {
        /* Dispose of jvmti (gdata->jvmti becomes NULL) */
        disposeEnvironment(gdata->jvmti);
    }

    /* Finish up logging. We reach here if JDWP is doing the exiting. */
    finish_logging(exit_code);  /* Only first call matters */

    /* Let's give the JNI a FatalError if non-exit 0, which is historic way */
    if ( exit_code != 0 ) {
        JNIEnv *env = NULL;
        jniFatalError(env, msg, error, exit_code);
    }

    /* Last chance to die, this kills the entire process. */
    forceExit(exit_code);
}
Пример #6
0
void forceExit(const char *msg)
{
	forceExit (msg, NULL);
}
Пример #7
0
// Display all processes and relevant network traffic using show function
void do_refresh()
{
	int rows; // number of terminal rows
	int cols; // number of terminal columns
	unsigned int proglen; // max length of the "PROGRAM" column

	getmaxyx(stdscr, rows, cols);	 /* find the boundaries of the screeen */
	if (cols < 60) {
		clear();
		mvprintw(0,0, "The terminal is too narrow! Please make it wider.\nI'll wait...");
		return;
	}

	if (cols > PROGNAME_WIDTH) cols = PROGNAME_WIDTH;

	proglen = cols - 53;

	refreshconninode();
	if (DEBUG || tracemode)
	{
		std::cout << "\nRefreshing:\n";
	}
	else
	{
		clear();
		mvprintw (0, 0, "%s", caption->c_str());
		attron(A_REVERSE);
		mvprintw (2, 0, "  PID USER     %-*.*s  DEV        SENT      RECEIVED       ", proglen, proglen, "PROGRAM");
		attroff(A_REVERSE);
	}
	ProcList * curproc = processes;
	ProcList * previousproc = NULL;
	int nproc = processes->size();
	/* initialise to null pointers */
	Line * lines [nproc];
	int n = 0, i = 0;
	double sent_global = 0;
	double recv_global = 0;

#ifndef NDEBUG
	// initialise to null pointers
	for (int i = 0; i < nproc; i++)
		lines[i] = NULL;
#endif

	while (curproc != NULL)
	{
		// walk though its connections, summing up their data, and
		// throwing away connections that haven't received a package
		// in the last PROCESSTIMEOUT seconds.
		assert (curproc != NULL);
		assert (curproc->getVal() != NULL);
		assert (nproc == processes->size());

		/* remove timed-out processes (unless it's one of the the unknown process) */
		if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec)
				&& (curproc->getVal() != unknowntcp)
				&& (curproc->getVal() != unknownudp)
				&& (curproc->getVal() != unknownip))
		{
			if (DEBUG)
				std::cout << "PROC: Deleting process\n";
			ProcList * todelete = curproc;
			Process * p_todelete = curproc->getVal();
			if (previousproc)
			{
				previousproc->next = curproc->next;
				curproc = curproc->next;
			} else {
				processes = curproc->getNext();
				curproc = processes;
			}
			delete todelete;
			delete p_todelete;
			nproc--;
			//continue;
		}
		else
		{
			// add a non-timed-out process to the list of stuff to show
			float value_sent = 0,
				value_recv = 0;

			if (viewMode == VIEWMODE_KBPS)
			{
				//std::cout << "kbps viemode" << std::endl;
				getkbps (curproc->getVal(), &value_recv, &value_sent);
			}
			else if (viewMode == VIEWMODE_TOTAL_KB)
			{
				//std::cout << "total viemode" << std::endl;
				gettotalkb(curproc->getVal(), &value_recv, &value_sent);
			}
			else if (viewMode == VIEWMODE_TOTAL_MB)
			{
				//std::cout << "total viemode" << std::endl;
				gettotalmb(curproc->getVal(), &value_recv, &value_sent);
			}
			else if (viewMode == VIEWMODE_TOTAL_B)
			{
				//std::cout << "total viemode" << std::endl;
				gettotalb(curproc->getVal(), &value_recv, &value_sent);
			}
			else
			{
				forceExit(false, "Invalid viewMode: %d", viewMode);
			}
			uid_t uid = curproc->getVal()->getUid();
#ifndef NDEBUG
			struct passwd * pwuid = getpwuid(uid);
			assert (pwuid != NULL);
			// value returned by pwuid should not be freed, according to
			// Petr Uzel.
			//free (pwuid);
#endif
			assert (curproc->getVal()->pid >= 0);
			assert (n < nproc);

			lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent,
					curproc->getVal()->pid, uid, curproc->getVal()->devicename);
			previousproc = curproc;
			curproc = curproc->next;
			n++;
#ifndef NDEBUG
			assert (nproc == processes->size());
			if (curproc == NULL)
				assert (n-1 < nproc);
			else
				assert (n < nproc);
#endif
		}
	}

	/* sort the accumulated lines */
	qsort (lines, nproc, sizeof(Line *), GreatestFirst);

	/* print them */
	for (i=0; i<nproc; i++)
	{
		if (i+3 < rows)
			lines[i]->show(i+3, proglen);
		recv_global += lines[i]->recv_value;
		sent_global += lines[i]->sent_value;
		delete lines[i];
	}
	if (tracemode || DEBUG) {
		/* print the 'unknown' connections, for debugging */
		ConnList * curr_unknownconn = unknowntcp->connections;
		while (curr_unknownconn != NULL) {
			std::cout << "Unknown connection: " <<
				curr_unknownconn->getVal()->refpacket->gethashstring() << std::endl;

			curr_unknownconn = curr_unknownconn->getNext();
		}
	}

	if ((!tracemode) && (!DEBUG)){
		attron(A_REVERSE);
		int totalrow = std::min(rows-1, 3+1+i);
		mvprintw (totalrow, 0, "  TOTAL        %-*.*s        %10.3f  %10.3f ", proglen, proglen, " ", sent_global, recv_global);
		if (viewMode == VIEWMODE_KBPS)
		{
			mvprintw (3+1+i, cols - 7, "KB/sec ");
		} else if (viewMode == VIEWMODE_TOTAL_B) {
			mvprintw (3+1+i, cols - 7, "B      ");
		} else if (viewMode == VIEWMODE_TOTAL_KB) {
			mvprintw (3+1+i, cols - 7, "KB     ");
		} else if (viewMode == VIEWMODE_TOTAL_MB) {
			mvprintw (3+1+i, cols - 7, "MB     ");
		}
		attroff(A_REVERSE);
		mvprintw (totalrow+1, 0, "");
		refresh();
	}
}
Пример #8
0
// Display all processes and relevant network traffic using show function
void do_refresh()
{
	refreshconninode();
	refreshcount++;

	ProcList * curproc = processes;
	ProcList * previousproc = NULL;
	int nproc = processes->size();
	/* initialise to null pointers */
	Line * lines [nproc];
	int n = 0;

#ifndef NDEBUG
	// initialise to null pointers
	for (int i = 0; i < nproc; i++)
		lines[i] = NULL;
#endif

	while (curproc != NULL)
	{
		// walk though its connections, summing up their data, and
		// throwing away connections that haven't received a package
		// in the last PROCESSTIMEOUT seconds.
		assert (curproc != NULL);
		assert (curproc->getVal() != NULL);
		assert (nproc == processes->size());

		/* remove timed-out processes (unless it's one of the the unknown process) */
		if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec)
				&& (curproc->getVal() != unknowntcp)
				&& (curproc->getVal() != unknownudp)
				&& (curproc->getVal() != unknownip))
		{
			if (DEBUG)
				std::cout << "PROC: Deleting process\n";
			ProcList * todelete = curproc;
			Process * p_todelete = curproc->getVal();
			if (previousproc)
			{
				previousproc->next = curproc->next;
				curproc = curproc->next;
			} else {
				processes = curproc->getNext();
				curproc = processes;
			}
			delete todelete;
			delete p_todelete;
			nproc--;
			//continue;
		}
		else
		{
			// add a non-timed-out process to the list of stuff to show
			float value_sent = 0,
				value_recv = 0;

			if (viewMode == VIEWMODE_KBPS)
			{
				//std::cout << "kbps viemode" << std::endl;
				getkbps (curproc->getVal(), &value_recv, &value_sent);
			}
			else if (viewMode == VIEWMODE_TOTAL_KB)
			{
				//std::cout << "total viemode" << std::endl;
				gettotalkb(curproc->getVal(), &value_recv, &value_sent);
			}
			else if (viewMode == VIEWMODE_TOTAL_MB)
			{
				//std::cout << "total viemode" << std::endl;
				gettotalmb(curproc->getVal(), &value_recv, &value_sent);
			}
			else if (viewMode == VIEWMODE_TOTAL_B)
			{
				//std::cout << "total viemode" << std::endl;
				gettotalb(curproc->getVal(), &value_recv, &value_sent);
			}
			else
			{
				forceExit(false, "Invalid viewMode: %d", viewMode);
			}
			uid_t uid = curproc->getVal()->getUid();
#ifndef NDEBUG
			struct passwd * pwuid = getpwuid(uid);
			assert (pwuid != NULL);
			// value returned by pwuid should not be freed, according to
			// Petr Uzel.
			//free (pwuid);
#endif
			assert (curproc->getVal()->pid >= 0);
			assert (n < nproc);

			lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent,
					curproc->getVal()->pid, uid, curproc->getVal()->devicename);
			previousproc = curproc;
			curproc = curproc->next;
			n++;
#ifndef NDEBUG
			assert (nproc == processes->size());
			if (curproc == NULL)
				assert (n-1 < nproc);
			else
				assert (n < nproc);
#endif
		}
	}

	/* sort the accumulated lines */
	qsort (lines, nproc, sizeof(Line *), GreatestFirst);

	if (tracemode || DEBUG)
		show_trace(lines, nproc);
	else
		show_ncurses(lines, nproc);

	if (refreshlimit != 0 && refreshcount >= refreshlimit)
		quit_cb(0);
}
Пример #9
0
/* OnLoad startup:
 *   Returning JNI_ERR will cause the java_g VM to core dump, be careful.
 */
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
    jvmtiError error;
    jvmtiCapabilities needed_capabilities;
    jvmtiCapabilities potential_capabilities;
    jint              jvmtiCompileTimeMajorVersion;
    jint              jvmtiCompileTimeMinorVersion;
    jint              jvmtiCompileTimeMicroVersion;

    /* See if it's already loaded */
    if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) {
        ERROR_MESSAGE(("Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options."));
        return JNI_ERR;
    }

    /* If gdata is defined and the VM died, why are we here? */
    if ( gdata!=NULL && gdata->vmDead ) {
        ERROR_MESSAGE(("JDWP unable to load, VM died"));
        return JNI_ERR;
    }

    /* Get global data area */
    gdata = get_gdata();
    if (gdata == NULL) {
        ERROR_MESSAGE(("JDWP unable to allocate memory"));
        return JNI_ERR;
    }
    gdata->isLoaded = JNI_TRUE;

    /* Start filling in gdata */
    gdata->jvm = vm;
    vmInitialized = JNI_FALSE;
    gdata->vmDead = JNI_FALSE;

    /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */
    error = JVM_FUNC_PTR(vm,GetEnv)
            (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1);
    if (error != JNI_OK) {
        ERROR_MESSAGE(("JDWP unable to access JVMTI Version 1 (0x%x),"
                       " is your J2SE a 1.5 or newer version?"
                       " JNIEnv's GetEnv() returned %d",
                       JVMTI_VERSION_1, error));
        forceExit(1); /* Kill entire process, no core dump */
    }

    /* Check to make sure the version of jvmti.h we compiled with
     *      matches the runtime version we are using.
     */
    jvmtiCompileTimeMajorVersion  = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR )
                                    >> JVMTI_VERSION_SHIFT_MAJOR;
    jvmtiCompileTimeMinorVersion  = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR )
                                    >> JVMTI_VERSION_SHIFT_MINOR;
    jvmtiCompileTimeMicroVersion  = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO )
                                    >> JVMTI_VERSION_SHIFT_MICRO;

    /* Check for compatibility */
    if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(),
                              jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) {

        ERROR_MESSAGE(("This jdwp native library will not work with this VM's "
                       "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d].",
                       jvmtiMajorVersion(),
                       jvmtiMinorVersion(),
                       jvmtiMicroVersion(),
                       jvmtiCompileTimeMajorVersion,
                       jvmtiCompileTimeMinorVersion,
                       jvmtiCompileTimeMicroVersion));

        /* Do not let VM get a fatal error, we don't want a core dump here. */
        forceExit(1); /* Kill entire process, no core dump wanted */
    }

    /* Parse input options */
    if (!parseOptions(options)) {
        /* No message necessary, should have been printed out already */
        /* Do not let VM get a fatal error, we don't want a core dump here. */
        forceExit(1); /* Kill entire process, no core dump wanted */
    }

    LOG_MISC(("Onload: %s", options));

    /* Get potential capabilities */
    (void)memset(&potential_capabilities,0,sizeof(potential_capabilities));
    error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities)
            (gdata->jvmti, &potential_capabilities);
    if (error != JVMTI_ERROR_NONE) {
        ERROR_MESSAGE(("JDWP unable to get potential JVMTI capabilities: %s(%d)",
                       jvmtiErrorText(error), error));
        return JNI_ERR;
    }

    /* Fill in ones that we must have */
    (void)memset(&needed_capabilities,0,sizeof(needed_capabilities));
    needed_capabilities.can_access_local_variables              = 1;
    needed_capabilities.can_generate_single_step_events         = 1;
    needed_capabilities.can_generate_exception_events           = 1;
    needed_capabilities.can_generate_frame_pop_events           = 1;
    needed_capabilities.can_generate_breakpoint_events          = 1;
    needed_capabilities.can_suspend                             = 1;
    needed_capabilities.can_generate_method_entry_events        = 1;
    needed_capabilities.can_generate_method_exit_events         = 1;
    needed_capabilities.can_generate_garbage_collection_events  = 1;
    needed_capabilities.can_maintain_original_method_order      = 1;
    needed_capabilities.can_generate_monitor_events             = 1;
    needed_capabilities.can_tag_objects                         = 1;

    /* And what potential ones that would be nice to have */
    needed_capabilities.can_force_early_return
        = potential_capabilities.can_force_early_return;
    needed_capabilities.can_generate_field_modification_events
        = potential_capabilities.can_generate_field_modification_events;
    needed_capabilities.can_generate_field_access_events
        = potential_capabilities.can_generate_field_access_events;
    needed_capabilities.can_get_bytecodes
        = potential_capabilities.can_get_bytecodes;
    needed_capabilities.can_get_synthetic_attribute
        = potential_capabilities.can_get_synthetic_attribute;
    needed_capabilities.can_get_owned_monitor_info
        = potential_capabilities.can_get_owned_monitor_info;
    needed_capabilities.can_get_current_contended_monitor
        = potential_capabilities.can_get_current_contended_monitor;
    needed_capabilities.can_get_monitor_info
        = potential_capabilities.can_get_monitor_info;
    needed_capabilities.can_pop_frame
        = potential_capabilities.can_pop_frame;
    needed_capabilities.can_redefine_classes
        = potential_capabilities.can_redefine_classes;
    needed_capabilities.can_redefine_any_class
        = potential_capabilities.can_redefine_any_class;
    needed_capabilities.can_get_owned_monitor_stack_depth_info
        = potential_capabilities.can_get_owned_monitor_stack_depth_info;
    needed_capabilities.can_get_constant_pool
        = potential_capabilities.can_get_constant_pool;
    {
        needed_capabilities.can_get_source_debug_extension      = 1;
        needed_capabilities.can_get_source_file_name            = 1;
        needed_capabilities.can_get_line_numbers                = 1;
        needed_capabilities.can_signal_thread
            = potential_capabilities.can_signal_thread;
    }

    /* Add the capabilities */
    error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities)
            (gdata->jvmti, &needed_capabilities);
    if (error != JVMTI_ERROR_NONE) {
        ERROR_MESSAGE(("JDWP unable to get necessary JVMTI capabilities."));
        forceExit(1); /* Kill entire process, no core dump wanted */
    }

    /* Initialize event number mapping tables */
    eventIndexInit();

    /* Set the initial JVMTI event notifications */
    error = set_event_notification(JVMTI_ENABLE, EI_VM_DEATH);
    if (error != JVMTI_ERROR_NONE) {
        return JNI_ERR;
    }
    error = set_event_notification(JVMTI_ENABLE, EI_VM_INIT);
    if (error != JVMTI_ERROR_NONE) {
        return JNI_ERR;
    }
    if (initOnUncaught || (initOnException != NULL)) {
        error = set_event_notification(JVMTI_ENABLE, EI_EXCEPTION);
        if (error != JVMTI_ERROR_NONE) {
            return JNI_ERR;
        }
    }

    /* Set callbacks just for 3 functions */
    (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));
    gdata->callbacks.VMInit             = &cbEarlyVMInit;
    gdata->callbacks.VMDeath            = &cbEarlyVMDeath;
    gdata->callbacks.Exception  = &cbEarlyException;
    error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
            (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
    if (error != JVMTI_ERROR_NONE) {
        ERROR_MESSAGE(("JDWP unable to set JVMTI event callbacks: %s(%d)",
                       jvmtiErrorText(error), error));
        return JNI_ERR;
    }

    LOG_MISC(("OnLoad: DONE"));
    return JNI_OK;
}
Пример #10
0
static jboolean
parseOptions(char *options)
{
    TransportSpec *currentTransport = NULL;
    char *end;
    char *current;
    int length;
    char *str;
    char *errmsg;

    /* Set defaults */
    gdata->assertOn     = DEFAULT_ASSERT_ON;
    gdata->assertFatal  = DEFAULT_ASSERT_FATAL;
    logfile             = DEFAULT_LOGFILE;

    /* Options being NULL will end up being an error. */
    if (options == NULL) {
        options = "";
    }

    /* Check for "help" BEFORE we add any environmental settings */
    if ((strcmp(options, "help")) == 0) {
        printUsage();
        forceExit(0); /* Kill entire process, no core dump wanted */
    }

    /* These buffers are never freed */
    {
        char *envOptions;

        /*
         * Add environmentally specified options.
         */
        envOptions = getenv("_JAVA_JDWP_OPTIONS");
        if (envOptions != NULL) {
            options = add_to_options(options, envOptions);
            if ( options==NULL ) {
                EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options");
            }
        }

        /*
         * Allocate a buffer for names derived from option strings. It should
         * never be longer than the original options string itself.
         * Also keep a copy of the options in gdata->options.
         */
        length = (int)strlen(options);
        gdata->options = jvmtiAllocate(length + 1);
        if (gdata->options == NULL) {
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options");
        }
        (void)strcpy(gdata->options, options);
        names = jvmtiAllocate(length + 1);
        if (names == NULL) {
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options");
        }

        transports = bagCreateBag(sizeof(TransportSpec), 3);
        if (transports == NULL) {
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"transports");
        }

    }

    current = names;
    end = names + length;
    str = options;

    while (*str) {
        char buf[100];
        /*LINTED*/
        if (!get_tok(&str, buf, (int)sizeof(buf), '=')) {
            goto syntax_error;
        }
        if (strcmp(buf, "transport") == 0) {
            currentTransport = bagAdd(transports);
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            currentTransport->name = current;
            current += strlen(current) + 1;
        } else if (strcmp(buf, "address") == 0) {
            if (currentTransport == NULL) {
                errmsg = "address specified without transport";
                goto bad_option_with_errmsg;
            }
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            currentTransport->address = current;
            current += strlen(current) + 1;
        } else if (strcmp(buf, "timeout") == 0) {
            if (currentTransport == NULL) {
                errmsg = "timeout specified without transport";
                goto bad_option_with_errmsg;
            }
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            currentTransport->timeout = atol(current);
            current += strlen(current) + 1;
        } else if (strcmp(buf, "launch") == 0) {
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            launchOnInit = current;
            current += strlen(current) + 1;
        } else if (strcmp(buf, "onthrow") == 0) {
            /* Read class name and convert in place to a signature */
            *current = 'L';
            /*LINTED*/
            if (!get_tok(&str, current + 1, (int)(end - current - 1), ',')) {
                goto syntax_error;
            }
            initOnException = current;
            while (*current != '\0') {
                if (*current == '.') {
                    *current = '/';
                }
                current++;
            }
            *current++ = ';';
            *current++ = '\0';
        } else if (strcmp(buf, "assert") == 0) {
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            if (strcmp(current, "y") == 0) {
                gdata->assertOn = JNI_TRUE;
                gdata->assertFatal = JNI_FALSE;
            } else if (strcmp(current, "fatal") == 0) {
                gdata->assertOn = JNI_TRUE;
                gdata->assertFatal = JNI_TRUE;
            } else if (strcmp(current, "n") == 0) {
                gdata->assertOn = JNI_FALSE;
                gdata->assertFatal = JNI_FALSE;
            } else {
                goto syntax_error;
            }
            current += strlen(current) + 1;
        } else if (strcmp(buf, "pause") == 0) {
            if ( !get_boolean(&str, &dopause) ) {
                goto syntax_error;
            }
            if ( dopause ) {
                do_pause();
            }
        } else if (strcmp(buf, "coredump") == 0) {
            if ( !get_boolean(&str, &docoredump) ) {
                goto syntax_error;
            }
        } else if (strcmp(buf, "errorexit") == 0) {
            if ( !get_boolean(&str, &(gdata->doerrorexit)) ) {
                goto syntax_error;
            }
        } else if (strcmp(buf, "exitpause") == 0) {
            errmsg = "The exitpause option removed, use -XX:OnError";
            goto bad_option_with_errmsg;
        } else if (strcmp(buf, "precrash") == 0) {
            errmsg = "The precrash option removed, use -XX:OnError";
            goto bad_option_with_errmsg;
        } else if (strcmp(buf, "logfile") == 0) {
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            logfile = current;
            current += strlen(current) + 1;
        } else if (strcmp(buf, "logflags") == 0) {
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            /*LINTED*/
            logflags = (unsigned)strtol(current, NULL, 0);
        } else if (strcmp(buf, "debugflags") == 0) {
            /*LINTED*/
            if (!get_tok(&str, current, (int)(end - current), ',')) {
                goto syntax_error;
            }
            /*LINTED*/
            gdata->debugflags = (unsigned)strtol(current, NULL, 0);
        } else if ( strcmp(buf, "suspend")==0 ) {
            if ( !get_boolean(&str, &suspendOnInit) ) {
                goto syntax_error;
            }
        } else if ( strcmp(buf, "server")==0 ) {
            if ( !get_boolean(&str, &isServer) ) {
                goto syntax_error;
            }
        } else if ( strcmp(buf, "strict")==0 ) { /* Obsolete, but accept it */
            if ( !get_boolean(&str, &isStrict) ) {
                goto syntax_error;
            }
        } else if ( strcmp(buf, "quiet")==0 ) {
            if ( !get_boolean(&str, &(gdata->quiet)) ) {
                goto syntax_error;
            }
        } else if ( strcmp(buf, "onuncaught")==0 ) {
            if ( !get_boolean(&str, &initOnUncaught) ) {
                goto syntax_error;
            }
        } else if ( strcmp(buf, "mutf8")==0 ) {
            if ( !get_boolean(&str, &(gdata->modifiedUtf8)) ) {
                goto syntax_error;
            }
        } else if ( strcmp(buf, "stdalloc")==0 ) { /* Obsolete, but accept it */
            if ( !get_boolean(&str, &useStandardAlloc) ) {
                goto syntax_error;
            }
        } else {
            goto syntax_error;
        }
    }

    /* Setup logging now */
    if ( logfile!=NULL ) {
        setup_logging(logfile, logflags);
        (void)atexit(&atexit_finish_logging);
    }

    if (bagSize(transports) == 0) {
        errmsg = "no transport specified";
        goto bad_option_with_errmsg;
    }

    /*
     * TO DO: Remove when multiple transports are allowed. (replace with
     * check below.
     */
    if (bagSize(transports) > 1) {
        errmsg = "multiple transports are not supported in this release";
        goto bad_option_with_errmsg;
    }


    if (!isServer) {
        jboolean specified = bagEnumerateOver(transports, checkAddress, NULL);
        if (!specified) {
            /* message already printed */
            goto bad_option_no_msg;
        }
    }

    /*
     * The user has selected to wait for an exception before init happens
     */
    if ((initOnException != NULL) || (initOnUncaught)) {
        initOnStartup = JNI_FALSE;

        if (launchOnInit == NULL) {
            /*
             * These rely on the launch=/usr/bin/foo
             * suboption, so it is an error if user did not
             * provide one.
             */
            errmsg = "Specify launch=<command line> when using onthrow or onuncaught suboption";
            goto bad_option_with_errmsg;
        }
    }

    return JNI_TRUE;

syntax_error:
    ERROR_MESSAGE(("JDWP option syntax error: %s=%s", AGENTLIB, options));
    return JNI_FALSE;

bad_option_with_errmsg:
    ERROR_MESSAGE(("JDWP %s: %s=%s", errmsg, AGENTLIB, options));
    return JNI_FALSE;

bad_option_no_msg:
    ERROR_MESSAGE(("JDWP %s: %s=%s", "invalid option", AGENTLIB, options));
    return JNI_FALSE;
}
Пример #11
0
int main (int argc, char** argv)
{
	process_init();

	device * devices = NULL;
	//dp_link_type linktype = dp_link_ethernet;
	int promisc = 0;

	int opt;
	while ((opt = getopt(argc, argv, "Vhbtpd:v:c:s")) != -1) {
		switch(opt) {
			case 'V':
				versiondisplay();
				exit(0);
			case 'h':
				help(false);
				exit(0);
			case 'b':
				bughuntmode = true;
				tracemode = true;
				break;
			case 't':
				tracemode = true;
				break;
			case 'p':
				promisc = 1;
				break;
			case 's':
				sortRecv = false;
				break;
			case 'd':
				refreshdelay = atoi(optarg);
				break;
			case 'v':
				viewMode = atoi(optarg) % VIEWMODE_COUNT;
				break;
			case 'c':
				refreshlimit = atoi(optarg);
				break;
			/*
			case 'f':
				argv++;
				if (strcmp (optarg, "ppp") == 0)
					linktype = dp_link_ppp;
				else if (strcmp (optarg, "eth") == 0)
					linktype = dp_link_ethernet;
				}
				break;
			*/
			default:
				help(true);
				exit(EXIT_FAILURE);
		}
	}

	while (optind < argc) {
		devices = new device (strdup(argv[optind++]), devices);
	}

	if (devices == NULL)
	{
		devices = get_default_devices();
        if ( devices == NULL )
        {
            std::cerr << "Not devices to monitor" << std::endl;
            return 0;
        }
	}

	if ((!tracemode) && (!DEBUG)){
		init_ui();
	}
	
	if (NEEDROOT && (geteuid() != 0))
		forceExit(false, "You need to be root to run NetHogs!");
		
	//use the Self-Pipe trick to interrupt the select() in the main loop
	self_pipe = create_self_pipe();
	if( self_pipe.first == -1 || self_pipe.second == -1 )
	{
		forceExit(false, "Error creating pipe file descriptors\n");
	}
	else
	{
		//add the self-pipe to allow interrupting select()
		pc_loop_fd_list.push_back(self_pipe.first);
	}

	char errbuf[PCAP_ERRBUF_SIZE];

	handle * handles = NULL;
	device * current_dev = devices;
	while (current_dev != NULL) {
		getLocal(current_dev->name, tracemode);

		dp_handle * newhandle = dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf);
		if (newhandle != NULL)
		{
			dp_addcb (newhandle, dp_packet_ip, process_ip);
			dp_addcb (newhandle, dp_packet_ip6, process_ip6);
			dp_addcb (newhandle, dp_packet_tcp, process_tcp);
			dp_addcb (newhandle, dp_packet_udp, process_udp);

			/* The following code solves sf.net bug 1019381, but is only available
			 * in newer versions (from 0.8 it seems) of libpcap
			 *
			 * update: version 0.7.2, which is in debian stable now, should be ok
			 * also.
			 */
			if (dp_setnonblock (newhandle, 1, errbuf) == -1)
			{
				fprintf(stderr, "Error putting libpcap in nonblocking mode\n");
			}
			handles = new handle (newhandle, current_dev->name, handles);
			
			if( pc_loop_use_select )
			{
				//some devices may not support pcap_get_selectable_fd
				int const fd = pcap_get_selectable_fd(newhandle->pcap_handle);
				if( fd != -1 )
				{
					pc_loop_fd_list.push_back(fd);
				}
				else
				{
					pc_loop_use_select = false;
					pc_loop_fd_list.clear();
					fprintf(stderr, "failed to get selectable_fd for %s\n", current_dev->name);
				}
			}			
		}
		else
		{
			fprintf(stderr, "Error opening handler for device %s\n", current_dev->name);
		}

		current_dev = current_dev->next;
	}

	signal (SIGINT, &quit_cb);

	fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
	struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));

	// Main loop:
	//
	//  Walks though the 'handles' list, which contains handles opened in non-blocking mode.
	//  This causes the CPU utilisation to go up to 100%. This is tricky:
	while (1)
	{
		bool packets_read = false;

		handle * current_handle = handles;
		while (current_handle != NULL)
		{
			userdata->device = current_handle->devicename;
			userdata->sa_family = AF_UNSPEC;
			int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs));
			if (retval < 0)
			{
				std::cerr << "Error dispatching: " << retval << std::endl;
			}
			else if (retval != 0)
			{
				packets_read = true;
			}
			current_handle = current_handle->next;
		}

		time_t const now = ::time(NULL);
 		if( last_refresh_time + refreshdelay <= now )
 		{
 			last_refresh_time = now;
 			if ((!DEBUG)&&(!tracemode))
			{
				// handle user input
				ui_tick();
			}
			do_refresh();
		}
 
		//if not packets, do a select() until next packet
		if (!packets_read)
		{
			if( !wait_for_next_trigger() )
			{
				//Exit the loop
				break;
			}
		}
	}
	
	//clean up
	clean_up();
}