// bfe2 - bochs connection // Copyright (c) 1999-2003 Brand Huntsman and Lee Salzman // #include "common.h" #include "functions.h" ////////////////////////////////////////////////////////////////////////// // global FILE *writepipe, *readpipe; uint bochs_running, bochs_offline, p_step; int bochs_pid; // local gint sigio_tag; uint bochs_died, starting_bochs; ////////////////////////////////////////////////////////////////////////// uint popen2( char *command, FILE **in, FILE **err ){ int ifd[2], efd [2]; if(in != NULL) pipe(ifd); if(err != NULL) pipe(efd); bochs_pid = fork(); if(bochs_pid == -1) return(0); if(bochs_pid == 0){ char *argv[4]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; g_print("CHILD-%d\n", bochs_pid); if(in != NULL) dup2(ifd[0], STDIN_FILENO); if(err != NULL) dup2(efd[1], STDERR_FILENO); freopen("/dev/null", "a", stdout); execv("/bin/sh", argv); exit(EXIT_FAILURE); } else { g_print("PARENT-%d\n", bochs_pid); if(err != NULL) *err = fdopen(efd[0], "r"); if(in != NULL) *in = fdopen(ifd[1], "w"); } return(1); } void sigchld_handler( int x ){ g_print("DEAD-%d\n", bochs_pid); if(starting_bochs) bfe_quit("Couldn't find Bochs"); bochs_died = 1; // this will call the toggle_bochs() function in main.c gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bochs_button), FALSE); } void sigio_handler( gpointer data, gint source, GdkInputCondition condition ){ ctrlStop(1); } void set_ctrl_online( gboolean v ){ ctrlEnableControls(v); breakpointsEnablePage(v); watchpointsEnablePage(v); memoryEnablePage(v); structuresEnablePage(v); prefsEnablePage(v); gtk_widget_set_sensitive(refreshall_button, v); } ////////////////////////////////////////////////////////////////////////// void hook_sigio( ){ sigio_tag = gdk_input_add(fileno(readpipe), GDK_INPUT_READ, sigio_handler, NULL); } void unhook_sigio( ){ gdk_input_remove(sigio_tag); } void bochsInit( ){ bochs_running = 0; bochs_offline = 1; bochs_died = 0; } void bochsShutdown( ){ signal(SIGCHLD, SIG_IGN); if(bochs_running){ unhook_sigio(); if(!bochs_died) kill(bochs_pid, SIGINT); bochs_running = 0; } if(bochs_died){ historyWrite("Lost connection to Bochs"); bochs_died = 0; } else if(!bochs_offline){ historyWrite("Terminating Bochs"); fprintf(writepipe, "q\n"); fclose(readpipe); fclose(writepipe); } set_ctrl_online(FALSE); bochs_offline = 1; } void bochsStart( ){ #ifdef __DEBUG__ g_print("BFE DEBUG: starting bochs... \n"); #endif historyReset(); g_print("START-%d\n", bochs_pid); starting_bochs = 1; signal(SIGCHLD, sigchld_handler); if(!popen2(BOCHS_PATH, &writepipe, &readpipe)){ #ifdef __DEBUG__ g_print("\tFAILED\n"); #endif historyWrite("BOCHS FAILED TO START"); return; // failed to start bochs } sleep(1); starting_bochs = 0; setbuf(readpipe, NULL); // disable line buffering setbuf(writepipe, NULL); bochs_offline = 0; g_print("START-OK-%d\n", bochs_pid); set_ctrl_online(TRUE); historyWrite("Starting Bochs"); prompt_read(); fprintf(writepipe, "s\n"); ctrlGetInstruction(); breakpointsReload(); watchpointsReload(); #ifdef __DEBUG__ g_print("\tOK\n"); #endif } void prompt_read( ){ char c; if(bochs_offline) return; #ifdef __DEBUG__ g_print("BFE DEBUG: reading prompt... \n"); #endif for(c = fgetc(readpipe); c != '<' && c != EOF; c = fgetc(readpipe)); if(c != '<') return; if(fscanf(readpipe, "bochs:%u>", &p_step) != 1) return; #ifdef __DEBUG__ g_print("\tOK\n"); #endif }