int delim_output(FILE *stream, int *need_delimp, int (*writer)(FILE *stream, void *data), void *data) { int o; /* If we don't need a delimiter, then we don't need to go * through a temporary stream. It's all the same whether * WRITER emits anything or not. */ if (!*need_delimp) { o = writer(stream, data); } else { struct memstream ms; if (memstream_init(&ms) < 0) return -1; o = writer(ms.stream, data); if (memstream_close(&ms) < 0) o = -1; if (o > 0 && ((*need_delimp && account_output(&o, fprintf(stream, ", ")) < 0) || fwrite(ms.buf, 1, ms.size, stream) != ms.size)) o = -1; memstream_destroy(&ms); } if (o < 0) return -1; *need_delimp = *need_delimp || o > 0; return o; }
memstream_t *memstream_open(bool writing) { memstream_t *stream; if (!g_buffer || !g_size) return NULL; stream = (memstream_t*)calloc(1, sizeof(*stream)); memstream_init(stream, g_buffer, g_size, writing); g_buffer = NULL; g_size = 0; return stream; }
int tb_init(void) { out = open("/dev/tty", O_WRONLY); in = fopen("/dev/tty", "r"); if (out == -1 || !in) return TB_EFAILED_TO_OPEN_TTY; out_fileno = out; in_fileno = fileno(in); if (init_term() < 0) return TB_EUNSUPPORTED_TERMINAL; if (pipe(winch_fds) < 0) return TB_EPIPE_TRAP_ERROR; struct sigaction sa; sa.sa_handler = sigwinch_handler; sa.sa_flags = 0; sigaction(SIGWINCH, &sa, 0); tcgetattr(out_fileno, &orig_tios); struct termios tios; memcpy(&tios, &orig_tios, sizeof(tios)); tios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); tios.c_oflag &= ~OPOST; tios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tios.c_cflag &= ~(CSIZE | PARENB); tios.c_cflag |= CS8; tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = 0; tcsetattr(out_fileno, TCSAFLUSH, &tios); memstream_init(&write_buffer, out_fileno, write_buffer_data, sizeof(write_buffer_data)); memstream_puts(&write_buffer, funcs[T_ENTER_CA]); memstream_puts(&write_buffer, funcs[T_ENTER_KEYPAD]); memstream_puts(&write_buffer, funcs[T_HIDE_CURSOR]); send_clear(); update_term_size(); cellbuf_init(&back_buffer, termw, termh); cellbuf_init(&front_buffer, termw, termh); cellbuf_clear(&back_buffer); cellbuf_clear(&front_buffer); init_ringbuffer(&inbuf, 4096); return 0; }
static void ondata(NETWORK_HANDLE handle, void* userptr) { CUBE_CONNECTION* conn; SVR_USER_CTX ctx; conn = (CUBE_CONNECTION*)userptr; ctx.conn = conn; os_mutex_lock(&room_mtx); while(1) { int ret; unsigned short len; char pkg_buf[sizeof(conn->recv_buf)]; MEM_STREAM stream; if(network_recvbuf_len(handle)<2) break; network_recvbuf_get(handle, &len, 0, sizeof(len)); if(network_recvbuf_len(handle)<len) break; network_recvbuf_get(handle, pkg_buf, sizeof(len), len-sizeof(len)); if(conn->nick[0]=='\0' && *((unsigned short*)pkg_buf)!=LOGIN_FILTER_ID) { network_disconnect(handle); break; } memstream_init(&stream, pkg_buf, len, len); ret = SVR_Dispatcher(&ctx, (STREAM*)&stream); if(ret!=ERR_NOERROR) { network_disconnect(handle); break; } network_recvbuf_commit(handle, len); } os_mutex_unlock(&room_mtx); }