/// cleans up game memory and SDL at exit void cleanup() { extern void clear_command(); extern void clear_console(); extern void clear_mdls(); extern void clear_sound(); recorder::stop(); cleanupserver(); /// "Use this function to set a window's input grab mode." /// https://wiki.libsdl.org/SDL_SetWindowGrab if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); /// "Use this function to set relative mouse mode." /// https://wiki.libsdl.org/SDL_SetRelativeMouseMode SDL_SetRelativeMouseMode(SDL_FALSE); /// "Use this function to toggle whether or not the cursor is shown." /// https://wiki.libsdl.org/SDL_ShowCursor SDL_ShowCursor(SDL_TRUE); cleargamma(); /// free octree memory freeocta(worldroot); clear_command(); clear_console(); clear_mdls(); clear_sound(); closelogfile(); /// "Use this function to clean up all initialized subsystems. You should call it upon all exit conditions." /// https://wiki.libsdl.org/SDL_Quit SDL_Quit(); }
void console_init() { int i; for (i = 0; i < NB_CONSOLES; i++) { consoles[i].used = false; consoles[i].lines = 25; consoles[i].cols = 80; consoles[i].attr = DEFAULT_ATTRIBUTE_VALUE; consoles[i].disp_cur = true; consoles[i].cur_x = 0; consoles[i].cur_y = 0; consoles[i].escape_char = false; consoles[i].ansi_escape_code = false; consoles[i].ansi_second_val = false; consoles[i].val = 0; consoles[i].val2 = 0; consoles[i].bright = 1; clear_console(i); } /* Enregistre le driver */ tty_driver = alloc_tty_driver(NB_CONSOLES); tty_driver->driver_name = "console"; tty_driver->devfs_name = "tty"; tty_driver->type = TTY_DRIVER_TYPE_CONSOLE; tty_driver->init_termios = tty_std_termios; tty_driver->ops = &console_ops; tty_register_driver(tty_driver); }
/* * 初期化 * * o 要求受けつけ用のメッセージバッファ ID をポートマネージャに登録 */ W init_console (void) { int i; ER error; /* * 要求受けつけ用のポートを初期化する。 */ recvport = get_port (sizeof (DDEV_REQ), sizeof (DDEV_REQ)); if (recvport <= 0) { dbg_printf ("CONSOLE: cannot make receive port.\n"); slp_tsk (); /* メッセージバッファ生成に失敗 */ } error = regist_port (CONSOLE_DRIVER, recvport); if (error != E_OK) { dbg_printf ("console: cannot regist port (error = %d)\n", error); } initialized = 1; clear_console (); }
/* --- Kernel entrypoint --- */ int kernel_main(mbinfo_t *mbinfo, int argc, char **argv, char **envp) { if(handler_install(tick) < 0) { panic("oh noes! where are my handlers"); } enable_interrupts(); clear_console(); show_cursor(); set_term_color(FGND_GREEN | BGND_BLACK); set_cursor(12, 34); printf("Hello World!\n"); set_cursor(15, 34); printf("Type \"cat\" now: \n"); wait_char('c'); putbyte('d'); wait_char('a'); putbyte('o'); wait_char('t'); putbyte('g'); set_cursor(16, 25); printf("That took %d seconds\n", seconds); printf("Yay kitties! - now what if you type \"dog\"?"); while(1) continue; }
void console_init() { disable_cursor(); if (console_attributes == 0) console_attributes = (FG_COLOR_BLUE | LIGHT | BG_COLOR_WHITE); clear_console(); }
int main(void) { try { #ifdef _MSC_VER std::wcout.imbue(std::locale("japanese"));//locale設定 #else std::wcout.imbue(std::locale(""));//locale設定 #endif std::wcout << L"クイズ ~あなたはパティシエ~" << std::endl << std::endl; if (2 == choose_one_from_two(L"開始…1 終了…2")) return 0; //xml read const auto xml = read_question_xml(u8"question.xml"); const auto correct_answer = make_array(3, 2, 2, 1, 3, 3, 3, 3, 1, 1, 4, 2, 1, 6, 4, 2, 2, 3, 1, 1, 3, 2); if(xml.size() != correct_answer.size()) return -1;//xmlの要素数と正解の数すべてが一致しない場合プログラム終了 const auto user_level = prelude_question();//事前質問 const auto sequence_of_questions_number = decide_sequence_of_questions_number(user_level);//問題順序の決定 std::wcout << L"回答ありがとうございます。それでは始めます。" << std::endl; pause_console(); clear_console(); //質問 ans_v ans; ans.reserve(11); for (const auto qid : sequence_of_questions_number) if (!ask(ans, user_level, correct_answer[qid], xml[qid])) break; const bool isAllcrear = std::all_of(ans.begin(), ans.end(), [](const auto& a) -> bool { return a.jude_correct; });//全問正解か調べる show_last_message(isAllcrear, ans.back().jude_correct, user_level); } catch (const std::exception& er) { std::cerr << er.what() << std::endl; return -1; } return 0; }
void show_last_message(const bool isAllcrear, const bool judge_correct, const uint8_t judge_user_level) { static const auto message = make_array( make_array( L"入力ミスか遊びだと信じています。", L"入力ミスか遊びだと信じています。", L"夢パティで再確認してもう一度挑戦してくださいね。", L"次は頑張ってくださいね。" ), make_array( L"簡単でしたよね?簡単すぎてすいません。", L"簡単でしたよね?簡単すぎてすいません。", L"あなたは本当に夢パティ愛してますね。", L"クリアおめでとうございます。" ) ); std::wcout << message[isAllcrear][judge_user_level - 1U] << std::endl; if (judge_correct && 4 == judge_user_level && !isAllcrear) std::wcout << L"次は全問正解を目指しましょう。" << std::endl; pause_console(); clear_console(); std::wcout << L"このゲームの問題は以上になります。もしこんなゲーム作ってほしい、問題を増やしてほしい等ありましたら、readmeに書かれましたメールアドレスへ。" << std::endl << L"新作ゲーム情報等は、readmeのリンクからアクセスできますブログに順次記載していきます。" << std::endl; }
void hold_on_state_change() { string input; if (state_changed_flag && !run_to_completion) { clear_console(); debug_print(); cout << "State has changed" << endl; cout << "Press any key to continue: or type 'run' to run to completion." << endl; getline(cin, input); state_changed_flag = false; if (input == "run") run_to_completion = true; } }
void cleanup() { recorder::stop(); cleanupserver(); SDL_ShowCursor(1); SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_SetGamma(1, 1, 1); freeocta(worldroot); extern void clear_command(); clear_command(); extern void clear_console(); clear_console(); extern void clear_mdls(); clear_mdls(); extern void clear_sound(); clear_sound(); SDL_Quit(); }
bool ask(ans_v& ans, const uint8_t user_level, const int correct_answer, const question_xml_data_c& nodelist) {//問題文表示, 回答入力 answer re; re.user_answer = input(nodelist.question.c_str(), nodelist.choices_num, static_cast<decltype(nodelist.choices_num)>(1));//キャストは保険 bool judge_continue = re.jude_correct = (correct_answer == re.user_answer); std::wcout << ((re.jude_correct) ? L"正解" : L"不正解") << L"です。" << std::endl; if (!re.jude_correct && 4 == user_level) { if(L"empty" == nodelist.explanation) std::wcout << L"正解は" << correct_answer << L"です。" << std::endl << nodelist.explanation << std::endl;//解説表示 if (nodelist.is_not_for_biginner) judge_continue = true; } pause_console(); clear_console(); ans.push_back(re); return judge_continue; }
void cleanup() { recorder::stop(); cleanupserver(); SDL_ShowCursor(1); SDL_WM_GrabInput(SDL_GRAB_OFF); cleargamma(); freeocta(worldroot); varsys::clear(); extern void clear_console(); clear_console(); extern void clear_mdls(); clear_mdls(); extern void clear_sound(); clear_sound(); closelogfile(); SDL_Quit(); }
void __panic(struct x86_registers regs, const char *func, const char *file, int line, const char *fmt, ...) { char buffer[BSIZE]; const char *panic_str = CONFIG_PANIC_STRING; size_t panic_str_len = strlen(panic_str); size_t buf_len = 0; va_list ap; int x, y, i, j; union x86_regs_u r; r.s_reg = regs; va_start(ap, fmt); /* Move the formatted message to the buffer[] */ buf_len = vsnprintf(buffer, BSIZE, fmt, ap); va_end(ap); /* Set the console color to white on red (Red Screen of Death :) */ set_console_attributes(BG_COLOR_RED | FG_COLOR_WHITE); clear_console(); /* Write the 'AKOSIX KERNEL PANIC' or other user-defined panic string centered */ kxya_print(CENTERED(panic_str_len), 1, BG_COLOR_BLACK | LIGHT | FG_COLOR_WHITE | BLINK, panic_str); /* The message with more ligher white, also centered */ kxya_print(CENTERED(buf_len), 3, BG_COLOR_RED|LIGHT|FG_COLOR_WHITE, buffer); set_xy(0, 5); /* Register dump */ for (i = 0; i <= X86_REG_EDI; i++) { kprintf("\t%s: %d [%x]\n", x86_register_name[i], r.a_reg[i], r.a_reg[i]); } kprintf("\n"); /* Segment registers are 16 bit long. Split the 32 bit array elements to high and low variables to overcome this. */ for (j = i = X86_REG_SS; i <= X86_REG_GS-1; i++, j++) { uint16_t high, low; high = r.a_reg[j] & 0x0000FFFF; low = r.a_reg[j] & 0xFFFF0000; kprintf("\t%s: %d [%x]\n", x86_register_name[i], high, high); kprintf("\t%s: %d [%x]\n", x86_register_name[++i], low, low); } // __backtrace(CONFIG_CONSOLE_WIDTH-LINE_LEN+5, 5, 5); /* Location of the panic file:function():line */ kxy_printf(0, CONSOLE_LAST_ROW, "%s:%s():%d", file, func, line); hang(); }
void cleanup() { holdscreenlock; recorder::stop(); cleanupserver(); if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(SDL_TRUE); cleargamma(); freeocta(worldroot); extern void clear_command(); clear_command(); extern void clear_console(); clear_console(); extern void clear_mdls(); clear_mdls(); extern void clear_sound(); clear_sound(); closelogfile(); SDL_Quit(); }
void cleanup() { recorder::stop(); cleanupserver(); showcursor(true); //#ifdef FAKESHOWCURSOR // if(scursor) SDL_FreeCursor(scursor); // scursor = ncursor = NULL; //#endif SDL_WM_GrabInput(SDL_GRAB_OFF); cleargamma(); freeocta(worldroot); extern void clear_command(); clear_command(); extern void clear_console(); clear_console(); extern void clear_mdls(); clear_mdls(); stopsound(); closelogfile(); SDL_Quit(); }
void clear_display_text_buffer () { int i; for (i = 0; i < DISPLAY_TEXT_BUFFER_SIZE; ++i) { if (!display_text_buffer[i].deleted && display_text_buffer[i].data != NULL && display_text_buffer[i].data[0] != '\0'){ free_text_message_data (display_text_buffer + i); } display_text_buffer[i].deleted= 1; } last_message = -1; last_server_message_time = cur_time; clear_console(); if(use_windowed_chat == 2){ clear_chat_wins(); } }
/************************************************************************ * control_console * * 引数: caller * packet * * 返値: E_NOSPT を返す。 * * 処理: * */ W control_console (ID caller, DDEV_CTL_REQ *packet) { DDEV_RES res; switch (packet->cmd) { case CONSOLE_CLEAR: clear_console (); res.body.ctl_res.dd = packet->dd; res.body.ctl_res.errcd = E_OK; res.body.ctl_res.errinfo = E_OK; snd_mbf (caller, sizeof (res), &res); return (E_OK); case CONSOLE_MOVE: if (packet->len != 2) { res.body.ctl_res.dd = packet->dd; res.body.ctl_res.errcd = E_PAR; res.body.ctl_res.errinfo = E_PAR; snd_mbf (caller, sizeof (res), &res); return (E_PAR); } set_curpos (packet->param[0], packet->param[1]); res.body.ctl_res.dd = packet->dd; res.body.ctl_res.errcd = E_OK; res.body.ctl_res.errinfo = E_OK; snd_mbf (caller, sizeof (res), &res); return (E_OK); default: res.body.ctl_res.dd = packet->dd; res.body.ctl_res.errcd = E_NOSPT; res.body.ctl_res.errinfo = E_NOSPT; snd_mbf (caller, sizeof (res), &res); return (E_NOSPT); } }
/* --- Kernel entrypoint --- */ int kernel_main() { /* * Tell the kernel memory allocator which memory it can't use. * It already knows not to touch kernel image. */ /* Everything above 16M */ lmm_remove_free( &malloc_lmm, (void*)USER_MEM_START, -8 - USER_MEM_START ); /* Everything below 1M */ lmm_remove_free( &malloc_lmm, (void*)0, 0x100000 ); if(handler_install() < 0) { return 0; } /* * initialize the PIC so that IRQs and * exception handlers don't overlap in the IDT. */ pic_init( BASE_IRQ_MASTER_BASE, BASE_IRQ_SLAVE_BASE ); clear_console(); show_cursor(); set_term_color(FGND_GREEN | BGND_BLACK); set_cursor(12, 34); putbytes("Hello World!\n", 13); while(1) { } return 0; }
void kernel_main(uint32_t mb_addr, uint32_t mb_magic) { if(mb_magic != MULTIBOOT_BOOTLOADER_MAGIC) { kprintf(PANIC,"Wrong Bootloader Magic\n"); for(;;); } multiboot_info_t* mb_info = (multiboot_info_t*)mb_addr; vbe_info_t* vbe_info = (vbe_info_t *)(mb_info->vbe_mode_info); uint32_t top = mb_info->mem_upper; uint32_t bot = mb_info->mem_lower; uint32_t mem = top+bot; clear_console(); char version[20]; get_version(version); kp("Welcome to ZOS v%s",version); kp("System Information"); kp(" Booting Flag: 0x%x",mb_info->flags); if(check_flag(mb_info->flags,0)) kp(" Available Memory: %d KB / %d MB",mem,mem/1024); if(check_flag(mb_info->flags,1)) kp(" Booting Device: 0x%x",mb_info->boot_device); if(check_flag(mb_info->flags,2)) { if(strlen((char*)mb_info->cmdline)>1) kp(" Booting Command: %s",(char*)mb_info->cmdline); } if(check_flag(mb_info->flags,3)) {} if(check_flag(mb_info->flags,4)) {} if(check_flag(mb_info->flags,5)) kernel_elf = elf_from_multiboot(mb_info); if(check_flag(mb_info->flags,6)) { /* multiboot_memory_map_t *mmap; kp ("mmap_addr = 0x%x, mmap_length = 0x%x", (unsigned) mb_info->mmap_addr, (unsigned) mb_info->mmap_length); for (mmap = (multiboot_memory_map_t *) mb_info->mmap_addr; (unsigned long) mmap < mb_info->mmap_addr + mb_info->mmap_length; mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof (mmap->size))) { kp (" size = 0x%x, base_addr = 0x%x%x," " length = 0x%x%x, type = 0x%x", (unsigned) mmap->size, mmap->addr >> 32, mmap->addr & 0xffffffff, mmap->len >> 32, mmap->len & 0xffffffff, (unsigned) mmap->type); } */ } gdt_init(); /* Global Descriptor Table */ idt_init(); /* Interrupt Descriptor Table */ isrs_init(); /* Interrupt Service Requests */ irq_init(); /* Hardware Interrupt Requests */ open_serial_output(); timer_init(); paging_init(mem); heap_init(); keyboard_init(); //pci_init(); kp("login: "******"Welcome to ZOS\n", "Hello!\n", "abcdefghijklmnopqrstuvwxyz1234567890\n", 0 }; for(int i=0;i!=3;i++) { for(int j = 0;j!=strlen(str[i]);j++) { gfx_print(str[i][j]); } } void render(window_t* win) { } void update(window_t* win) { surface_fill(win->surface,0,rgb(255,255,255)); key_event_t* head; int len; keyboard_event_get(&head,&len); for(int i=0;i!=len;i++) { key_event_t* eve = head+i; if(eve->type == KEY_DOWN) { gfx_print(eve->character); } } keyboard_event_clear(); rect_t trect = {0,0,720,20}; for(int i=0;i!=24;i++) { if(strlen(gfx_con_buf[i])) { surface_t* surf = font_render(gfx_con_buf[i],col); surface_blend(surf,0,win->surface,&trect); surface_free(surf); } trect.y += 20; } }
/** *Process changes in neighborhood or/and topology. *Re-calculates the neighborhood/topology if there *are any updates - then calls the right functions to *update the routing table. *@return 0 */ void olsr_process_changes(void) { struct pcf *tmp_pc_list; #ifdef DEBUG if (changes_neighborhood) OLSR_PRINTF(3, "CHANGES IN NEIGHBORHOOD\n"); if (changes_topology) OLSR_PRINTF(3, "CHANGES IN TOPOLOGY\n"); if (changes_hna) OLSR_PRINTF(3, "CHANGES IN HNA\n"); #endif if (!changes_neighborhood && !changes_topology && !changes_hna) return; if (olsr_cnf->debug_level > 0 && olsr_cnf->clear_screen && isatty(1)) { clear_console(); printf(" *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host); } if (changes_neighborhood) { if (olsr_cnf->lq_level < 1) { olsr_calculate_mpr(); } else { olsr_calculate_lq_mpr(); } } /* calculate the routing table */ if (changes_neighborhood || changes_topology || changes_hna) { olsr_calculate_routing_table(false); } if (olsr_cnf->debug_level > 0) { if (olsr_cnf->debug_level > 2) { olsr_print_mid_set(); #ifdef LINUX_NETLINK_ROUTING olsr_print_gateway_entries(); #endif if (olsr_cnf->debug_level > 3) { if (olsr_cnf->debug_level > 8) { olsr_print_duplicate_table(); } olsr_print_hna_set(); } } olsr_print_link_set(); olsr_print_neighbor_table(); olsr_print_two_hop_neighbor_table(); olsr_print_tc_table(); } for (tmp_pc_list = pcf_list; tmp_pc_list != NULL; tmp_pc_list = tmp_pc_list->next) { tmp_pc_list->function(changes_neighborhood, changes_topology, changes_hna); } changes_neighborhood = false; changes_topology = false; changes_hna = false; changes_force = false; }
// runs the current mission - called each tick. Don't call in non-mission mode. // Returns 1 if the game continues, 0 if game over (although this is currently ignored and the game over status is set by this function) static int run_mission(void) { // int i; // special mission-specific code: switch(game.mission_index) { case MISSION_TUTORIAL1: switch(mission_state.phase) { case MPHASE1_START: clear_console(CONSOLE_SYSTEM); // play_interface_sound(SAMPLE_BLIP3, TONE_2C); write_mission_text(PRINT_COL_WHITE, /*"Program initialised. Spawning process 0.\n\*/ "\nWelcome!\n\ To begin, select the blue base process near the centre of the display (by left-clicking on it)."); write_mission_text(PRINT_COL_LBLUE, "\n\n(For information about controls, or to quit, open the system panel at any time by clicking on the Sy button in the top right of the display)."); mission_state.phase = MPHASE1_SELECT; break; case MPHASE1_SELECT: if (command.selected_core [0] == 0) // can assume builder is process 0 { clear_console(CONSOLE_SYSTEM); play_interface_sound(SAMPLE_BLIP3, TONE_2C); write_mission_text(PRINT_COL_WHITE, "This process is a builder/harvester base.\ \nIt harvests raw data from the nearby data well and allocates it. Then it uses allocated data to \ build new processes.\ \n\nBut the data from a single well won't be enough! Build a mobile harvester by clicking on the \"harvester\" button on the left of the display."); mission_state.phase = MPHASE1_BUILD; } break; case MPHASE1_BUILD: if (w.core[1].exists > 0) { clear_console(CONSOLE_SYSTEM); play_interface_sound(SAMPLE_BLIP3, TONE_2C); write_mission_text(PRINT_COL_WHITE, "The harvester will take a few seconds to finish constructing.\ \nSelect it and tell it to move near a different data well. Data wells are shown in yellow on the map at the bottom right of the display."); // \n\nSelect it and tell it to move near a different data well. Data wells are shown in yellow on the map at the bottom right of the display."); write_mission_text(PRINT_COL_LBLUE, "\n\n(Give movement commands by right-clicking on the display or the map. You don't need to click exactly on the well, just nearby.)"); mission_state.phase = MPHASE1_FIND_WELL; } break; case MPHASE1_FIND_WELL: if (distance_oct_xyxy(w.core[1].core_position.x, w.core[1].core_position.y, w.data_well[1].position.x, w.data_well[1].position.y) < al_itofix(600) || distance_oct_xyxy(w.core[1].core_position.x, w.core[1].core_position.y, w.data_well[2].position.x, w.data_well[2].position.y) < al_itofix(600)) { clear_console(CONSOLE_SYSTEM); play_interface_sound(SAMPLE_BLIP3, TONE_2C); write_mission_text(PRINT_COL_WHITE, "You can leave the harvester alone, and it will gather data to take back to the base.\ \n\nNow find the base again (you can click on the map to move the display around) and tell it to build an \"attacker\" process."); mission_state.phase = MPHASE1_BUILD_ATTACKERS; }
int main(void) { srand(time(NULL)); /* * Creates a stream and checks to see if the Processes.txt file exists. * If it doesn't, the program returns an error and will exit. */ ifstream inputProcesses; inputProcesses.open("Processes.txt"); while(!inputProcesses.is_open()) { cout << "ERROR: file Process.txt can not be opened. Please check that Process.txt is in the correct folder." << endl; exit(0); } //Checks the Processes.txt file for any errors in formatting check_file(inputProcesses); initialize_console(); /* * Initially read in inputs and build processes * Run long term scheduler to put a few processes into NEW * Allocate memory for processes in NEW to put into READY * Run short term scheduler to bring a process from READY->RUNNING * Loop time cycles and process interrupts */ initialize_memory(); /* * Initial process arrival, the OS always starts with something running? * This potentially simplifies the main loop and makes the fetch-execute-interrupt * logic more apparent. */ new_process_arrival(retrieve_next_process(inputProcesses)); /* Fetch-execute-interrupt begins * Wait 0.1 seconds to simulate the cycle * Process in RUN executes for a 0.1 cycle * Check for interrupts or preemption * If process is EXIT then run short term scheduler */ /* * The main do while loop for the program, which exits when the user inputs * 'exit' as a string to end the program. The string input is the main string * for processing user input, and cycle_count is a counter for how many cycles * have been looped. */ string input = ""; int cycle_count = 0; /* * Do we want to initially run to completion? * NOTE: This position will change, we will want to * allow the user to change this at ANY POINT. */ /* cout << "Run OS to completion? (y or n):\n"; getline(cin, input); // Temporary Logic and Display, CHANGE LATER if (input == "y") run_to_completion = true; else if (input == "n") run_to_completion = false; else cout << "Wrong input: run_to_completion is false"; // User echo initially to make sure we are reading input correctly. cout << "You entered: " << input << endl << endl; cout << "BEGINNING SIMULATION" << endl; */ do { /* * Check if any new processes have arrived first. * If no processes have arrived, only passes a NULL reference. */ new_process_arrival(retrieve_next_process(inputProcesses));; hold_on_state_change(); /* * Long term FCFS scheduler * Simulates process arrival. */ long_term_scheduler(); hold_on_state_change(); /* * Short term preemptive scheduler. * Implemented as Round Robin with a 10 cycle time slice. */ short_term_scheduler(); hold_on_state_change(); // Increase cycle count of the fetch-execute-interrupt cycle cycle_count++; // Run the current process in the RUNNING state execute_running_process(); // Check for any interrupts check_io_interrupt(); hold_on_state_change(); // Check active IO devices process_io_devices(); hold_on_state_change(); // Debugging print for the new and ready queues debug_print(); // User interaction cout << "Type 'exit' to exit the program:\n"; cout << "Press enter to advance one clock cycle (this is temporary):\n>"; if(run_to_completion != true){ getline(cin, input); } else if(new_queue.empty() && blocked_queue.empty() && running_process.check_state("NULL") && ready_queue.empty()){ // Also check if simulation is finished. If file is empty, and all queues are empty. //Sleep for 2000 milliseconds cout << "Simulation has finished" << endl; input = "exit"; } else{ Sleep(2000); } // User echo initially to make sure we are reading input correctly. cout << "You entered: " << input << endl << endl; clear_console(); } while (input != "exit"); cout << "System exiting\n"; // User must press a key to exit getline(cin, input); return 0; }
bool start_client(void) { clear_console(); printf("\n\033[32m[WIFSS] Starting Client...\033[0m\n\n"); init_global_variables(); char address[BUFFER]; char *args[BUFFER]; int16_t nbArgs = -1; do { printf("-> Server IP: "); prompt_keyboard(address); free_args(args, &nbArgs); parse_command(address, args, &nbArgs); } while(nbArgs != 1); int32_t port; char portBuffer[BUFFER]; do { printf("-> Server Port: "); prompt_keyboard(portBuffer); free_args(args, &nbArgs); parse_command(portBuffer, args, &nbArgs); if(nbArgs == 1) { port = strtoul(args[0], NULL, 10); } else { port = -1; } } while(port < 0 || port > 65535); struct addrinfo *servinfo; struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; int16_t status = getaddrinfo(address, args[0], &hints, &servinfo); if(status != 0) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while trying to get some information about your host: %s.\033[0m\n\n", gai_strerror(status)); exit(EXIT_FAILURE); } char buffer[BUFFER]; // Some stuff to set a timeout on `connect` int16_t sock = -1; int8_t error = 0; socklen_t lenght = sizeof(error); int16_t nbFds = -1; fd_set readfds; do { for(struct addrinfo *tmp = servinfo; tmp != NULL; tmp = tmp->ai_next) { /* Only for previous iterations */ if(sock != -1 && close(sock) == -1) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while closing a socket: %s.\033[0m\n\n", strerror(errno)); exit(EXIT_FAILURE); } /* ____________________________ */ sock = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); if(sock == -1) { printf("\n\033[31m[WIFSS] Error while creating an endpoint for communication with server: %s.\033[0m\n\n", strerror(errno)); return false; } // Before the connection procedure, we'll set the socket as NON-BLOCKING fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) | O_NONBLOCK); // Let's launch the connection procedure connect(sock, tmp->ai_addr, tmp->ai_addrlen); if(errno != EINPROGRESS) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while running the connection procedure to: "); print_endpoint(tmp); printf(" (%s).\033[0m\n\n", strerror(errno)); continue; } // Let's now set a watch dog of 3 seconds on it FD_ZERO(&readfds); FD_SET(sock, &readfds); nbFds = select(sock + 1, &readfds, NULL, NULL, &(struct timeval){3, 0}); if(nbFds == 0) { // The timeout has been elapsed... printf("\n\033[31m[WIFSS] Error while connecting to "); print_endpoint(tmp); printf(": timeout reached.\033[0m\n"); continue; } else if(nbFds == -1) { // Again ? An error occurred... fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while waiting for the connection procedure ending: %s.\033[0m\n\n", strerror(errno)); exit(EXIT_FAILURE); } else { // Fetch the buffered SYNC data [see @server/commands.c] recv(sock, buffer, BUFFER, false); if(strcmp(buffer, CLIENT_SERVER_SYNC)) { printf("%s\n", buffer); exit(EXIT_FAILURE); } } // Two cases: The connection has been established OR a f*cking new error occurred (before the timeout !)... if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &lenght) != 0) { fprintf(stderr, "\n\033[31m[WIFSS] An error occurred while retrieving some information about the socket: %s.\033[0m\n\n", gai_strerror(status)); exit(EXIT_FAILURE); } if(error == 0) { // For the future, let's set again the socket as BLOCKING fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, false) ^ O_NONBLOCK); // SSL stuffs SSL *ssl = SSL_new(core_variables.ctx); if(ssl == NULL) { fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t enable the SSL layer on the socket.\n\n"); exit(EXIT_FAILURE); } if(SSL_set_cipher_list(ssl, (const char *const)"HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4") != 1) { fprintf(stderr, "\n\n\033[31mSSL Error: Couldn\'t set the ciphers list.\n\n"); exit(EXIT_FAILURE); } SSL_set_fd(ssl, sock); if(SSL_connect(ssl) <= 0) { printf("\n\n\033[31m[WIFSS] Couldn\'t create a TLS tunnel with the host...\033[0m\n\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } // SSL Verification + Certificate information if(SSL_get_verify_result(ssl) != X509_V_OK) { fprintf(stderr, "\n\n\033[31mSSL Error: The result got from SSL is not valid (is your certificate correct ?).\n\n"); exit(EXIT_FAILURE); } X509 *cert = SSL_get_peer_certificate(ssl); if(cert == NULL) { fprintf(stderr, "\n\n\033[31mSSL Error: No certificate was sent by server.\n\n"); exit(EXIT_FAILURE); } printf("\n\033[34m\tTLS cipher used for this connection: %s\n", SSL_get_cipher(ssl)); char *str = NULL; printf("\tServer certificate:\n"); str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); printf("\t\tSubject: %s\n", (str != NULL ? str : "None")); OPENSSL_free(str); str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); printf("\t\tIssuer : %s\033[0m\n", (str != NULL ? str : "None")); OPENSSL_free(str); X509_free(cert); // __________________________________________ core_variables.ssl = ssl; printf("\n\033[32m[WIFSS] Connected to "); print_endpoint(tmp); printf(".\033[0m\n"); strncpy(buffer, "", BUFFER); if(SSL_read(ssl, buffer, BUFFER) <= 0) { printf("\n\033[31m[WIFSS] Couldn\'t get your ID from server, exiting now.\033[0m\n\n"); exit(EXIT_FAILURE); } uint16_t idTemp = get_second_args_group_as_integer(buffer); printf("\n\033[32m[WIFSS] Your ID on the server is %d.\033[0m\n\n", idTemp); /* We save the ID of the client for the future */ core_variables.client_id = idTemp; break; } else { printf("\n\033[31m[WIFSS] Error while connecting to "); print_endpoint(tmp); printf(": %s.\033[0m\n", strerror(errno)); } } if(core_variables.client_id != -1) { // Yeah... We've to `break` the loop a second time break; } else { printf("\nWould you like to retry now ? (YES / no)\n\n"); if(!prompt_yes_no(buffer, args, &nbArgs)) { printf("\n"); return false; } } } while(true);