tcp-listen.cpp (1500B)
1 #include "linux.hpp" 2 3 struct reader 4 { 5 reader(c_str in) : s{in.begin()} {} 6 bool peek(char& out) 7 { 8 if (peeked) 9 { 10 out = buf; 11 return true; 12 } 13 assert(s); 14 if (not *s) 15 return false; 16 out = buf = *s++; 17 peeked = true; 18 return true; 19 } 20 void pop() 21 { 22 assert(peeked); 23 peeked = false; 24 } 25 26 private: 27 char const* s; 28 bool peeked = false; 29 char buf; 30 }; 31 32 bool isdigit(char c) 33 { 34 return '0' <= c and c <= '9'; 35 } 36 37 bool decimal(reader& r, uint64_t& out) 38 { 39 char c; 40 if (not r.peek(c)) 41 return false; 42 if (not isdigit(c)) 43 return false; 44 r.pop(); 45 uint64_t val = c - '0'; 46 while (r.peek(c) and isdigit(c)) 47 { 48 r.pop(); 49 val = val * 10 + c - '0'; 50 } 51 out = val; 52 return true; 53 } 54 55 void test(c_str in, uint64_t expect) 56 { 57 reader r{in}; 58 uint64_t x; 59 assert(decimal(r, x)); 60 assert(x == expect); 61 } 62 63 #define tst(x) test(#x, x##ull) 64 65 int main(int argc, char* argv[], char* envp[]) 66 { 67 tst(0); 68 tst(1); 69 tst(9); 70 tst(10); 71 tst(11); 72 tst(9001); 73 test("130AAXX1", 130); 74 tst(18446744073709551615); 75 76 if (argc <= 2) 77 return 1; 78 reader rdr{argv[1]}; 79 uint64_t port; 80 if (not decimal(rdr, port)) 81 return 2; 82 if (port > 65535) 83 return 3; 84 85 file sock = *socket(2/*AF_INET*/, 1/*SOCK_STREAM*/, 0/*IPPROTO_IP*/); 86 in_addr addr{static_cast<uint16_t>(port), 0/*IN_ADDR_ANY*/}; 87 *bind(sock, addr); 88 *listen(sock, 1); 89 socklen_t addr_len = sizeof(addr); 90 file conn = *accept(sock, &addr, &addr_len); 91 *dup(conn, stdin); 92 *dup(conn, stdout); 93 *close(conn); 94 *close(sock); 95 *execve(argv[2], argv+2, envp); 96 }