int main(int argc, char **argv) { struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = sigint_handler; DIE_IF_ERR(io_loop_init(&loop)); DIE_IF_ERR(io_tcp_server(&loop, &server, "0.0.0.0", "5000")); DIE_IF_ERR(io_listen_start(&server, incoming_connection)); DIE_IF_ERR(sigaction(SIGINT, &act, NULL)); puts("echo server is up..."); DIE_IF_ERR(io_loop_run(&loop)); return 0; }
int main(int argc, char **argv) { struct sigaction act; io_handle_t serv1, serv2, serv3, servr, watcher; sdp_session_t *session; memset(&act, 0, sizeof(act)); act.sa_handler = sigint_handler; DIE_IF_ERR(storage_segregate(&storage, 12, 512)); DIE_IF_ERR(io_loop_init(&loop)); DIE_IF_ERR(io_file(&loop, &backup, "backup.txt", O_RDWR)); DIE_IF_ERR(io_inotify(&loop, &watcher)); DIE_IF_ERR(io_tcp_server(&loop, &serv1, "0.0.0.0", "3000")); DIE_IF_ERR(io_tcp_server(&loop, &serv2, "0.0.0.0", "4000")); DIE_IF_ERR(io_tcp_server(&loop, &serv3, "0.0.0.0", "5000")); DIE_IF_ERR(io_rfcomm_server(&loop, &servr, BDADDR_ANY, 4)); lseek(backup.fd, 0, SEEK_END); DIE_IF_ERR(io_watch_start(&watcher, "/dev", IN_CREATE | IN_DELETE, file_changed)); DIE_IF_ERR(io_channel(&channel)); DIE_IF_ERR(io_channel_join(&channel, &backup, backup_updated)); DIE_IF_ERR(io_channel_join(&channel, &tcp1, serl_updated)); if(try_serial(&loop, &serl) == -1) puts("warning: arduino not connected."); else DIE_IF_ERR(io_publish_start(&serl, &channel, data_published)); DIE_IF_ERR(io_listen_start(&serv1, new_tcp1_conn)); DIE_IF_ERR(io_listen_start(&serv2, new_tcp2_conn)); DIE_IF_ERR(io_listen_start(&serv3, new_tcp3_conn)); DIE_IF_ERR(io_listen_start(&servr, new_rfcm_conn)); session = io_rfcomm_advertise(4, name, desc, uuid128); DIE_IF_ERR(sigaction(SIGINT, &act, NULL)); puts("pi server is up..."); DIE_IF_ERR(io_loop_run(&loop)); io_channel_close(&channel); storage_collapse(&storage); io_rfcomm_unadvertise(session); return 0; }
static struct child* start_child(struct msg_shex_hello* shex_hello) { if (shex_hello->nr_argv < 2) die(ECOMM, "insufficient arguments given"); SCOPED_RESLIST(rl_args); char** child_args = read_child_arglist(shex_hello->nr_argv); reslist_pop_nodestroy(rl_args); struct child_start_info csi = { .flags = CHILD_SETSID, .exename = child_args[0], .argv = (const char* const *) child_args + 1, .pty_setup = setup_pty, .pty_setup_data = shex_hello, .deathsig = -SIGHUP, }; if (shex_hello->si[0].pty_p) csi.flags |= CHILD_PTY_STDIN; if (shex_hello->si[1].pty_p) csi.flags |= CHILD_PTY_STDOUT; if (shex_hello->si[2].pty_p) csi.flags |= CHILD_PTY_STDERR; return child_start(&csi); } static void __attribute__((noreturn)) re_exec_as_root() { execlp("su", "su", "-c", xaprintf("%s stub", orig_argv0), NULL); die_errno("execlp of su"); } int stub_main(int argc, const char** argv) { if (argc != 1) die(EINVAL, "this command is internal"); /* XMKRAW_SKIP_CLEANUP so we never change from raw back to cooked * mode on exit. The connection dies on exit anyway, and * resetting the pty can send some extra bytes that can confuse * our peer. */ if (isatty(0)) xmkraw(0, XMKRAW_SKIP_CLEANUP); if (isatty(1)) xmkraw(1, XMKRAW_SKIP_CLEANUP); printf(FB_ADB_PROTO_START_LINE "\n", build_time, (int) getuid()); fflush(stdout); struct msg_shex_hello* shex_hello; struct msg* mhdr = read_msg(0, read_all_adb_encoded); if (mhdr->type == MSG_EXEC_AS_ROOT) re_exec_as_root(); // Never returns if (mhdr->type != MSG_SHEX_HELLO || mhdr->size < sizeof (struct msg_shex_hello)) { die(ECOMM, "bad hello"); } shex_hello = (struct msg_shex_hello*) mhdr; struct child* child = start_child(shex_hello); struct stub stub; memset(&stub, 0, sizeof (stub)); stub.child = child; struct fb_adb_sh* sh = &stub.sh; sh->process_msg = stub_process_msg; sh->max_outgoing_msg = shex_hello->maxmsg; sh->nrch = 5; struct channel** ch = xalloc(sh->nrch * sizeof (*ch)); ch[FROM_PEER] = channel_new(fdh_dup(0), shex_hello->stub_recv_bufsz, CHANNEL_FROM_FD); ch[FROM_PEER]->window = UINT32_MAX; ch[FROM_PEER]->adb_encoding_hack = true; replace_with_dev_null(0); ch[TO_PEER] = channel_new(fdh_dup(1), shex_hello->stub_send_bufsz, CHANNEL_TO_FD); replace_with_dev_null(1); ch[CHILD_STDIN] = channel_new(child->fd[0], shex_hello->si[0].bufsz, CHANNEL_TO_FD); ch[CHILD_STDIN]->track_bytes_written = true; ch[CHILD_STDIN]->bytes_written = ringbuf_room(ch[CHILD_STDIN]->rb); ch[CHILD_STDOUT] = channel_new(child->fd[1], shex_hello->si[1].bufsz, CHANNEL_FROM_FD); ch[CHILD_STDOUT]->track_window = true; ch[CHILD_STDERR] = channel_new(child->fd[2], shex_hello->si[2].bufsz, CHANNEL_FROM_FD); ch[CHILD_STDERR]->track_window = true; sh->ch = ch; io_loop_init(sh); PUMP_WHILE(sh, (!channel_dead_p(ch[FROM_PEER]) && !channel_dead_p(ch[TO_PEER]) && (!channel_dead_p(ch[CHILD_STDOUT]) || !channel_dead_p(ch[CHILD_STDERR])))); if (channel_dead_p(ch[FROM_PEER]) || channel_dead_p(ch[TO_PEER])) { // // If we lost our peer connection, make sure the child sees // SIGHUP instead of seeing its stdin close: just drain any // internally-buffered IO and exit. When we lose the pty, the // child gets SIGHUP. // // Make sure we won't be getting any more commands. channel_close(ch[FROM_PEER]); channel_close(ch[TO_PEER]); PUMP_WHILE(sh, (!channel_dead_p(ch[FROM_PEER]) || !channel_dead_p(ch[TO_PEER]))); // Drain output buffers channel_close(ch[CHILD_STDIN]); PUMP_WHILE(sh, !channel_dead_p(ch[CHILD_STDIN])); return 128 + SIGHUP; } // // Clean exit: close standard handles and drain IO. Peer still // has no idea that we're exiting. Get exit status, send that to // peer, then cleanly shut down the peer connection. // dbg("clean exit"); channel_close(ch[CHILD_STDIN]); channel_close(ch[CHILD_STDOUT]); channel_close(ch[CHILD_STDERR]); PUMP_WHILE (sh, (!channel_dead_p(ch[CHILD_STDIN]) || !channel_dead_p(ch[CHILD_STDOUT]) || !channel_dead_p(ch[CHILD_STDERR]))); send_exit_message(child_wait(child), sh); channel_close(ch[TO_PEER]); PUMP_WHILE(sh, !channel_dead_p(ch[TO_PEER])); channel_close(ch[FROM_PEER]); PUMP_WHILE(sh, !channel_dead_p(ch[FROM_PEER])); return 0; }