static int ansi_emulate(const char *str, FILE *stream) { int rv = 0; const char *pos = str; fflush(stream); while (*pos) { pos = strstr(str, "\033["); if (pos) { size_t len = pos - str; if (len) { size_t out_len = write_console(str, len); rv += out_len; if (out_len < len) return rv; } str = pos + 2; rv += 2; pos = set_attr(str); rv += pos - str; str = pos; } else { size_t len = strlen(str); rv += write_console(str, len); return rv; } } return rv; }
static int get_target_device_size(int fd, const char *blk_device, uint64_t *device_size) { int data_device; struct ext4_super_block sb; struct fs_info info; info.len = 0; /* Only len is set to 0 to ask the device for real size. */ data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC); if (data_device < 0) { write_console(fd, "Error opening block device (%s)\n", strerror(errno)); return -1; } if (lseek64(data_device, 1024, SEEK_SET) < 0) { write_console(fd, "Error seeking to superblock\n"); adb_close(data_device); return -1; } if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) { write_console(fd, "Error reading superblock\n"); adb_close(data_device); return -1; } ext4_parse_sb(&sb, &info); *device_size = info.len; adb_close(data_device); return 0; }
void set_verity_enabled_state_service(int fd, void* cookie) { bool enable = (cookie != NULL); if (kAllowDisableVerity) { char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; char propbuf[PROPERTY_VALUE_MAX]; int i; bool any_changed = false; property_get("ro.secure", propbuf, "0"); if (strcmp(propbuf, "1")) { write_console(fd, "verity not enabled - ENG build\n"); goto errout; } property_get("ro.debuggable", propbuf, "0"); if (strcmp(propbuf, "1")) { write_console( fd, "verity cannot be disabled/enabled - USER build\n"); goto errout; } property_get("ro.hardware", propbuf, ""); snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); fstab = fs_mgr_read_fstab(fstab_filename); if (!fstab) { write_console(fd, "Failed to open %s\nMaybe run adb root?\n", fstab_filename); goto errout; } /* Loop through entries looking for ones that vold manages */ for (i = 0; i < fstab->num_entries; i++) { if(fs_mgr_is_verified(&fstab->recs[i])) { if (!set_verity_enabled_state(fd, fstab->recs[i].blk_device, fstab->recs[i].mount_point, enable)) { any_changed = true; } } } if (any_changed) { write_console( fd, "Now reboot your device for settings to take effect\n"); } } else { write_console(fd, "%s-verity only works for userdebug builds\n", enable ? "enable" : "disable"); } errout: adb_close(fd); }
/* * We can't run the VM in the main thread (because it has to handle events). * So we run the VM in this thread. */ static DWORD WINAPI vm_thread_routine(LPVOID lpvParam) { // Print arguments that we are using JVMSPI_PrintRaw("Running VM"); JVMSPI_PrintRaw("\n"); for (int i = 1; i < _argc; i++) { JVMSPI_PrintRaw(" "); JVMSPI_PrintRaw(_argv[i]); JVMSPI_PrintRaw("\n"); } // Call this before any other Jvm_ functions. JVM_Initialize(); int argc = _argc; char ** argv = _argv; // Ignore arg[0] -- the name of the program. argc --; argv ++; while (true) { int n = JVM_ParseOneArg(argc, argv); if (n < 0) { JVMSPI_DisplayUsage(NULL); return -1; } else if (n == 0) { break; } argc -= n; argv += n; } if (LogConsole) { write_console("Console output logged at \n"); write_console(logfilename); write_console("\n"); for (int index=0; index<_argc; index++) { log_console(_argv[index]); log_console(" "); } log_console("\n"); } if (!WriteConsole) { write_console("On-screen console output disabled.\n"); } int code = JVM_Start(NULL, NULL, argc, argv); JVMSPI_Exit(code); SHOULD_NOT_REACH_HERE(); return 0; }
static VMINT32 measurement(VM_THREAD_HANDLE thread_handle, void* user_data) { VMINT measured_result; handle_details* details; hx711_task current_task; write_console("thread enter\n"); details = (handle_details*) user_data; get_task(details, ¤t_task); enter_standby(¤t_task); while (1) { get_task(details, ¤t_task); if (current_task.op == TERMINATE) { break; } if (current_task.op == WAIT) { enter_standby(¤t_task); continue; } if (current_task.op != A128) { wait_result(¤t_task); read_result(¤t_task); clock_setup_pulses(¤t_task); } wait_result(¤t_task); measured_result = read_result(¤t_task); current_task.callback(current_task.callback_env, measured_result); enter_standby(¤t_task); } write_console("thread exit\n"); enter_standby(¤t_task); vm_mutex_lock(&details->mutex); vm_dcl_close(current_task.sda_handle); vm_dcl_close(current_task.scl_handle); current_task.callback(current_task.callback_env, 0); vm_free(details); return 0; }
int putchar(int c) { char str[2] = "\0"; str[0] = (char)c; write_console(str, 1); return 0; }
static void doit (DDEV_REQ *packet) { switch (packet->header.msgtyp) { case DEV_OPN: /* デバイスのオープン */ if (!initialized) { init_console (); } open_console (packet->header.mbfid, &(packet->body.opn_req)); break; case DEV_CLS: /* デバイスのクローズ */ close_console (packet->header.mbfid, &(packet->body.cls_req)); break; case DEV_REA: read_console (packet->header.mbfid, &(packet->body.rea_req)); break; case DEV_WRI: write_console (packet->header.mbfid, &(packet->body.wri_req)); break; case DEV_CTL: control_console (packet->header.mbfid, &(packet->body.ctl_req)); break; } }
static void xenboot_write_console(struct console *console, const char *string, unsigned len) { unsigned int linelen, off = 0; const char *pos; while (off < len && NULL != (pos = strchr(string+off, '\n'))) { linelen = pos-string+off; if (off + linelen > len) break; write_console(0, string+off, linelen); write_console(0, "\r\n", 2); off += linelen + 1; } if (off < len) write_console(0, string+off, len-off); }
static int f() { char buf = '1'; while (1) { read_console(&buf, 1); write_console(&buf, 1); } return 0; }
void JVMSPI_PrintRaw(const char* s) { if (WriteConsole) { write_console(s); } if (LogConsole) { log_console(s); } }
void JVMSPI_Exit(int code) { if (_log_file) { fclose(_log_file); _log_file = NULL; } Os::stop_ticks(); if (_WindowSystem && StickyConsole) { write_console("VM has terminated\n"); } else { write_console("\nBye Bye\n"); if (_hwndMain) { SendMessage(_hwndMain, WM_CLOSE, 0, 0); } } ExitThread(0); }
static ssize_t do_write(void *handle, char *buffer, size_t size) { struct recall *rc = &recall_buffer; switch(use_console) { case C_ATTACHED: return write_console(handle, buffer, size); case C_NONE: if ( handle == Serror->handle ) { if ( ask_attach(FALSE) ) { if ( attach_console() ) return write_console(handle, buffer, size); } } break; case C_READ: break; case C_NEVER: return size; } if ( !rc->data ) { rc->allocated = 512; rc->data = PL_malloc(rc->allocated); rc->size = 0; } if ( size + rc->size <= rc->allocated ) { memcpy(&rc->data[rc->size], buffer, size); rc->size += size; } else if ( size >= rc->allocated ) { memcpy(rc->data, &buffer[size-rc->allocated], rc->allocated); rc->size = rc->allocated; } else { int leave = rc->allocated - size; memmove(rc->data, &rc->data[rc->size-leave], leave); memcpy(&rc->data+leave, buffer, size); rc->size = rc->allocated; } return size; }
void close_hx711(ADC_HANDLE handle, void (*callback)(void*, int), void* callback_env) { handle_details* details; details = get_handle_details(handle); if (details != NULL) { open_handles[handle] = NULL; new_task(details, TERMINATE, 0, callback, callback_env); write_console("close\n"); } }
// Log the message to /jvm.log static void log_console(const char* s) { static bool first = true; if (first && _log_file == NULL) { char buf[128], buf2[140]; if (LogByDate) { SYSTEMTIME st; GetSystemTime(&st); // example: jvm.log.2002-09-10.13-11-05 sprintf(buf, "%s.%4d-%2d-%2d.%2d-%2d-%2d", logfilename, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); for (int i=0; i<sizeof(buf); i++) { if (buf[i] == ' ') { buf[i] = '0'; } } } else { sprintf(buf, "%s", logfilename); } // Try to save to "\Storage Card\cldc_vm.log" if possible. This // makes it easier to view the output on an ARM device emulator. sprintf(buf2, "%s%s", "\\Storage Card", buf); if ((_log_file = fopen(buf2, "w")) == NULL) { _log_file = fopen(buf, "w"); } if (_log_file == NULL) { write_console("Console creation failed: \n"); write_console(logfilename); write_console("\n"); } first = false; } if (_log_file != NULL) { fprintf(_log_file, "%s", s); fflush(_log_file); } }
static int test() { // CHECK: reg c1: 0 printf("reg c1: %d\n", register_console(&c1)); // CHECK: reg c2: 0 printf("reg c2: %d\n", register_console(&c2)); write_console(NULL, 0); // CHECK: read ret: 1 char tmp; printf("read ret: %d\n", read_console(&tmp, 1)); unregister_console(&c1); return 0; }
ADC_HANDLE open_hx711(int scl_pin, int sda_pin) { ADC_HANDLE handle = 0; handle_details* details; hx711_task* task; while (open_handles[handle] != NULL) { handle++; if (handle > MAX_HANDLE) { return ADC_HANDLE_INVALID; } } details = vm_calloc(sizeof(handle_details)); if (details == NULL) { return ADC_HANDLE_INVALID; } task = &details->task; task->scl_handle = vm_dcl_open(VM_DCL_GPIO, scl_pin); if (task->scl_handle == VM_DCL_HANDLE_INVALID) { vm_free(details); return ADC_HANDLE_INVALID; } vm_dcl_control(task->scl_handle, VM_DCL_GPIO_COMMAND_SET_MODE_0, NULL); vm_dcl_control(task->scl_handle, VM_DCL_GPIO_COMMAND_SET_DIRECTION_OUT, NULL); vm_dcl_control(task->scl_handle, VM_DCL_GPIO_COMMAND_WRITE_HIGH, NULL); task->sda_handle = vm_dcl_open(VM_DCL_GPIO, sda_pin); if (task->sda_handle == VM_DCL_HANDLE_INVALID) { vm_dcl_close(task->scl_handle); vm_free(details); return ADC_HANDLE_INVALID; } vm_dcl_control(task->sda_handle, VM_DCL_GPIO_COMMAND_SET_MODE_0, NULL); vm_dcl_control(task->sda_handle, VM_DCL_GPIO_COMMAND_SET_DIRECTION_IN, NULL); vm_mutex_init(&details->mutex); task->op = WAIT; task->delay = 100; task->callback = dummy_callback; task->callback_env = NULL; open_handles[handle] = details; write_console("open\n"); vm_thread_create(measurement, (void*) details, (VM_THREAD_PRIORITY) 0); return handle; }
void Loggable::hermes_log_message(const char code, const char* msg) const { logger_monitor.enter(); //print the message if(!write_console(code, msg)) printf("%s", msg); //safe fallback printf("\n"); //write a new line HermesLogEventInfo* info = this->hermes_build_log_info(code); //print to file char* log_file_name = (this->logFileName ? this->logFileName : Loggable::staticLogFileName); if(log_file_name) { FILE* file = fopen(log_file_name, "at"); if(file != nullptr) { //check whether log file was already written std::map<std::string, bool>::const_iterator found = logger_written.find(log_file_name); if(found == logger_written.end()) { //first write, write delimited to a file logger_written[log_file_name] = true; fprintf(file, "\n"); for(int i = 0; i < HERMES_LOG_FILE_DELIM_SIZE; i++) fprintf(file, "-"); fprintf(file, "\n\n"); } //get time time_t now; time(&now); struct tm* now_tm = gmtime(&now); char time_buf[BUF_SZ]; strftime(time_buf, BUF_SZ, "%y%m%d-%H:%M", now_tm); //write fprintf(file, "%s\t%s\n", time_buf, msg); fclose(file); if(this->verbose_callback != nullptr) this->verbose_callback(msg); } } delete info; logger_monitor.leave(); }
static int attach_console(void) { static int done = 0; switch(done) { case 0: if ( AllocConsole() ) { cin = GetStdHandle(STD_INPUT_HANDLE); cout = GetStdHandle(STD_OUTPUT_HANDLE); cerr = GetStdHandle(STD_ERROR_HANDLE); if ( cin != INVALID_HANDLE_VALUE && cerr != INVALID_HANDLE_VALUE && cout != INVALID_HANDLE_VALUE ) { use_console = C_ATTACHED; done = 1; if ( recall_buffer.size ) { write_console(Soutput, recall_buffer.data, recall_buffer.size); recall_buffer.size = 0; recall_buffer.allocated = 0; PL_free(recall_buffer.data); recall_buffer.data = NULL; } return TRUE; } } done = -1; return FALSE; case 1: return TRUE; /* already done so */ default: return FALSE; /* tried but failed */ } }
/* * write_jsonlog * Write logs in json format. */ static void write_jsonlog(ErrorData *edata) { StringInfoData buf; TransactionId txid = GetTopTransactionIdIfAny(); /* * Disable logs to server, we don't want duplicate entries in * the server. */ edata->output_to_server = false; /* Determine whether message is enabled for server log output */ if (!is_log_level_output(edata->elevel, log_min_messages)) return; initStringInfo(&buf); /* Initialize string */ appendStringInfoChar(&buf, '{'); /* Timestamp */ setup_formatted_log_time(); appendJSONLiteral(&buf, "timestamp", formatted_log_time, true); /* Username */ if (MyProcPort && MyProcPort->user_name) appendJSONLiteral(&buf, "user", MyProcPort->user_name, true); /* Database name */ if (MyProcPort && MyProcPort->database_name) appendJSONLiteral(&buf, "dbname", MyProcPort->database_name, true); /* Process ID */ if (MyProcPid != 0) appendStringInfo(&buf, "\"pid\":%d,", MyProcPid); /* Remote host and port */ if (MyProcPort && MyProcPort->remote_host) { appendJSONLiteral(&buf, "remote_host", MyProcPort->remote_host, true); if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') appendJSONLiteral(&buf, "remote_port", MyProcPort->remote_port, true); } /* Session id */ if (MyProcPid != 0) appendStringInfo(&buf, "\"session_id\":\"%lx.%x\",", (long) MyStartTime, MyProcPid); /* Virtual transaction id */ /* keep VXID format in sync with lockfuncs.c */ if (MyProc != NULL && MyProc->backendId != InvalidBackendId) appendStringInfo(&buf, "\"vxid\":\"%d/%u\",", MyProc->backendId, MyProc->lxid); /* Transaction id */ if (txid != InvalidTransactionId) appendStringInfo(&buf, "\"txid\":%u,", GetTopTransactionIdIfAny()); /* Error severity */ appendJSONLiteral(&buf, "error_severity", (char *) error_severity(edata->elevel), true); /* SQL state code */ if (edata->sqlerrcode != ERRCODE_SUCCESSFUL_COMPLETION) appendJSONLiteral(&buf, "state_code", unpack_sql_state(edata->sqlerrcode), true); /* Error detail or Error detail log */ if (edata->detail_log) appendJSONLiteral(&buf, "detail_log", edata->detail_log, true); else if (edata->detail) appendJSONLiteral(&buf, "detail", edata->detail, true); /* Error hint */ if (edata->hint) appendJSONLiteral(&buf, "hint", edata->hint, true); /* Internal query */ if (edata->internalquery) appendJSONLiteral(&buf, "internal_query", edata->internalquery, true); /* Error context */ if (edata->context) appendJSONLiteral(&buf, "context", edata->context, true); /* user query --- only reported if not disabled by the caller */ if (is_log_level_output(edata->elevel, log_min_error_statement) && debug_query_string != NULL && !edata->hide_stmt) { appendJSONLiteral(&buf, "statement", debug_query_string, true); if (edata->cursorpos > 0) appendStringInfo(&buf, "\"cursor_position\":%d,", edata->cursorpos); else if (edata->internalpos > 0) appendStringInfo(&buf, "\"internal_position\":%d,", edata->internalpos); } /* File error location */ if (Log_error_verbosity >= PGERROR_VERBOSE) { StringInfoData msgbuf; initStringInfo(&msgbuf); if (edata->funcname && edata->filename) appendStringInfo(&msgbuf, "%s, %s:%d", edata->funcname, edata->filename, edata->lineno); else if (edata->filename) appendStringInfo(&msgbuf, "%s:%d", edata->filename, edata->lineno); appendJSONLiteral(&buf, "file_location", msgbuf.data, true); pfree(msgbuf.data); } /* Application name */ if (application_name && application_name[0] != '\0') appendJSONLiteral(&buf, "application_name", application_name, true); /* Error message */ appendJSONLiteral(&buf, "message", edata->message, false); /* Finish string */ appendStringInfoChar(&buf, '}'); appendStringInfoChar(&buf, '\n'); /* Write to stderr, if enabled */ if ((Log_destination & LOG_DESTINATION_STDERR) != 0) { if (Logging_collector && redirection_done && !am_syslogger) write_pipe_chunks(buf.data, buf.len); else write_console(buf.data, buf.len); } /* If in the syslogger process, try to write messages direct to file */ if (am_syslogger) write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_STDERR); /* Cleanup */ pfree(buf.data); /* Continue chain to previous hook */ if (prev_log_hook) (*prev_log_hook) (edata); }
static void banner (void) { write_console (banner_message, sizeof (banner_message)); }
bool hermes_log_message_if(bool cond, const HermesLogEventInfo& info, const char* msg, ...) { if (cond) { logger_monitor.enter(); //print message to a buffer (since vfprintf modifies arglist such that it becomes unusable) //not safe, but C does not offer any other multiplatform solution. Since vsnprintf modifies the var-args, it cannot be called repeatedly. #define BUF_SZ 2048 bool emphasize = false; bool new_block = true; char text[BUF_SZ]; char* text_contents = text + 1; if (msg[0] == '!') { emphasize = true; msg++; } if (msg[0] == ' ') { text[0] = ' '; new_block = false; } else { if (info.code == 'E') Teuchos::show_stacktrace(); text[0] = info.code; text[1] = ' '; text_contents++; new_block = true; } //print the message va_list arglist; va_start(arglist, msg); vsprintf(text_contents, msg, arglist); va_end(arglist); //print the message if (emphasize && new_block) printf("\n"); if (!write_console(info.code, emphasize, text)) printf("%s", text); //safe fallback printf("\n"); //write a new line //print to file if (info.log_file != NULL) { FILE* file = fopen(info.log_file, "at"); if (file != NULL) { //check whether log file was already written std::map<std::string, bool>::const_iterator found = logger_written.find(info.log_file); if (found == logger_written.end()) { //first write, write delimited to a file logger_written[info.log_file] = true; fprintf(file, "\n"); for(int i = 0; i < HERMES_LOG_FILE_DELIM_SIZE; i++) fprintf(file, "-"); fprintf(file, "\n\n"); } //build a long version of location std::ostringstream location; location << '('; if (info.src_function != NULL) { location << info.src_function; if (info.src_file != NULL) location << '@'; } if (info.src_file != NULL) location << info.src_file << ':' << info.src_line; location << ')'; //get time time_t now; time(&now); struct tm* now_tm = gmtime(&now); char time_buf[BUF_SZ]; strftime(time_buf, BUF_SZ, "%y%m%d-%H:%M", now_tm); //write if (emphasize && new_block) fprintf(file, "\n\n"); fprintf(file, "%s\t%s %s\n", time_buf, text, location.str().c_str()); fclose(file); } } logger_monitor.leave(); } return cond; }
static int f() { const char *c = "Hello, world!\n"; write_console(c, strlen(c)); return 0; }
static int domU_write_console(uint32_t vtermno, const char *data, int len) { return write_console(vtermno, data, len); }
/* Turn verity on/off */ static int set_verity_enabled_state(int fd, const char *block_device, const char* mount_point, bool enable) { uint32_t magic_number; const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER : VERITY_METADATA_MAGIC_DISABLE; uint64_t device_length = 0; int device = -1; int retval = -1; if (make_block_device_writable(block_device)) { write_console(fd, "Could not make block device %s writable (%s).\n", block_device, strerror(errno)); goto errout; } device = adb_open(block_device, O_RDWR | O_CLOEXEC); if (device == -1) { write_console(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno)); write_console(fd, "Maybe run adb remount?\n"); goto errout; } // find the start of the verity metadata if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) { write_console(fd, "Could not get target device size.\n"); goto errout; } if (lseek64(device, device_length, SEEK_SET) < 0) { write_console(fd, "Could not seek to start of verity metadata block.\n"); goto errout; } // check the magic number if (adb_read(device, &magic_number, sizeof(magic_number)) != sizeof(magic_number)) { write_console(fd, "Couldn't read magic number!\n"); goto errout; } if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) { write_console(fd, "Verity already disabled on %s\n", mount_point); goto errout; } if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) { write_console(fd, "Verity already enabled on %s\n", mount_point); goto errout; } if (magic_number != VERITY_METADATA_MAGIC_NUMBER && magic_number != VERITY_METADATA_MAGIC_DISABLE) { write_console(fd, "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length); goto errout; } if (lseek64(device, device_length, SEEK_SET) < 0) { write_console(fd, "Could not seek to start of verity metadata block.\n"); goto errout; } if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) { write_console( fd, "Could not set verity %s flag on device %s with error %s\n", enable ? "enabled" : "disabled", block_device, strerror(errno)); goto errout; } write_console(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point); retval = 0; errout: if (device != -1) adb_close(device); return retval; }
static DWORD WINAPI console_thread(LPVOID unused) { unsigned char buffer[BUFFER_SIZE]; DWORD bytes; int start, end = 0, c, parampos = 0, state = TEXT; int params[MAX_PARAMS]; while (1) { /* read next chunk of bytes from the pipe */ if (!ReadFile(hread, buffer + end, BUFFER_SIZE - end, &bytes, NULL)) { /* exit if pipe has been closed or disconnected */ if (GetLastError() == ERROR_PIPE_NOT_CONNECTED || GetLastError() == ERROR_BROKEN_PIPE) break; /* ignore other errors */ continue; } /* scan the bytes and handle ANSI control codes */ bytes += end; start = end = 0; while (end < bytes) { c = buffer[end++]; switch (state) { case TEXT: if (c == ESCAPE) { /* print text seen so far */ if (end - 1 > start) write_console(buffer + start, end - 1 - start); /* then start parsing escape sequence */ start = end - 1; memset(params, 0, sizeof(params)); parampos = 0; state = ESCAPE; } break; case ESCAPE: /* continue if "\033[", otherwise bail out */ state = (c == BRACKET) ? BRACKET : TEXT; break; case BRACKET: /* parse [0-9;]* into array of parameters */ if (c >= '0' && c <= '9') { params[parampos] *= 10; params[parampos] += c - '0'; } else if (c == ';') { /* * next parameter, bail out if out of * bounds */ parampos++; if (parampos >= MAX_PARAMS) state = TEXT; } else { /* * end of escape sequence, change * console attributes */ set_attr(c, params, parampos + 1); start = end; state = TEXT; } break; } } /* print remaining text unless parsing an escape sequence */ if (state == TEXT && end > start) { /* check for incomplete UTF-8 sequences and fix end */ if (buffer[end - 1] >= 0x80) { if (buffer[end -1] >= 0xc0) end--; else if (end - 1 > start && buffer[end - 2] >= 0xe0) end -= 2; else if (end - 2 > start && buffer[end - 3] >= 0xf0) end -= 3; } /* print remaining complete UTF-8 sequences */ if (end > start) write_console(buffer + start, end - start); /* move remaining bytes to the front */ if (end < bytes) memmove(buffer, buffer + end, bytes - end); end = bytes - end; } else { /* all data has been consumed, mark buffer empty */ end = 0; } } /* check if the console font supports unicode */ warn_if_raster_font(); CloseHandle(hread); return 0; }