decompiled_code:
struct addrinfo *__fastcall get_my_addr(char *service)
{
int v1; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_socktype = 0LL;
*(_OWORD *)&req.ai_addr = 0LL;
req.ai_next = 0LL;
*(_QWORD *)&req.ai_flags = 0x200000001LL;
req.ai_socktype = 1;
v1 = getaddrinfo(0LL, service, &req, &pai);
exit_gai_error(v1);
return pai;
}

canonical_decompiled_code:
struct addrinfo *__fastcall func11(char *service)
{
int v1; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_socktype = 0LL;
*(_OWORD *)&req.ai_addr = 0LL;
req.ai_next = 0LL;
*(_QWORD *)&req.ai_flags = 0x200000001LL;
req.ai_socktype = 1;
v1 = getaddrinfo(0LL, service, &req, &pai);
func10(v1);
return pai;
}

original_code:
struct addrinfo *
get_my_addr(char *port) {
  struct addrinfo hints, *addr;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = 2;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0x0001;
  int ret = getaddrinfo(((void *)0), port, &hints, &addr);
  exit_gai_error(ret);
  return addr;
}

canonical_original_code:
struct addrinfo *get_my_addr(char *port) {
  struct addrinfo hints; struct addrinfo *addr;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = 2;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0x0001;
  int ret = getaddrinfo(((void *)0), port, &hints, &addr);
  exit_gai_error(ret);
  return addr;
}

variable_types:
port
char *

variable_types: struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; unsigned int ai_addrlen; struct sockaddr { unsigned short sa_family; char sa_data[14]; } *ai_addr; char *ai_canonname; struct addrinfo *ai_next; } *

user_defined_types: struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; unsigned int ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; }


repo: kazu-yamamoto/latency-bench

decompiled_code:
struct addrinfo *__fastcall get_peer_addr(const char *a1, const char *a2)
{
int v2; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_flags = 0LL;
*(_OWORD *)&req.ai_addrlen = 0LL;
*(_OWORD *)&req.ai_canonname = 0LL;
*(_QWORD *)&req.ai_family = 0x100000002LL;
v2 = getaddrinfo(a1, a2, &req, &pai);
exit_gai_error(v2);
return pai;
}

canonical_decompiled_code:
struct addrinfo *__fastcall func12(const char *a1, const char *a2)
{
int v2; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_flags = 0LL;
*(_OWORD *)&req.ai_addrlen = 0LL;
*(_OWORD *)&req.ai_canonname = 0LL;
*(_QWORD *)&req.ai_family = 0x100000002LL;
v2 = getaddrinfo(a1, a2, &req, &pai);
func10(v2);
return pai;
}

original_code:
struct addrinfo*
get_peer_addr(char *peer, char *port) {
  struct addrinfo hints, *addr;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = 2;
  hints.ai_socktype = SOCK_STREAM;
  int ret = getaddrinfo(peer, port, &hints, &addr);
  exit_gai_error(ret);
  return addr;
}

canonical_original_code:
struct addrinfo *get_peer_addr(char *peer, char *port) {
  struct addrinfo hints; struct addrinfo *addr;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = 2;
  hints.ai_socktype = SOCK_STREAM;
  int ret = getaddrinfo(peer, port, &hints, &addr);
  exit_gai_error(ret);
  return addr;
}

variable_types:
peer
char *

variable_types: ret int

return_type: struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; unsigned int ai_addrlen; struct sockaddr { unsigned short sa_family; char sa_data[14]; } *ai_addr; char *ai_canonname; struct addrinfo *ai_next; } *


decompiled_code:
__int64 __fastcall get_socket(int *a1)
{
unsigned int v1; // er12

v1 = socket(a1[1], a1[2], a1[3]);
exit_error(v1, "socket");
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func13(int *a1)
{
unsigned int v1; // er12

v1 = socket(a1[1], a1[2], a1[3]);
func9(v1, "socket");
return v1;
}

original_code:
int
get_socket(struct addrinfo *addr) {
  int sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
  exit_error(sock, "socket");
  return sock;
}

variable_types: sock int

return_type: int

user_defined_types: struct sockaddr { unsigned short sa_family; char sa_data[14]; }


decompiled_code:
void __fastcall bind_socket(int a1, __int64 a2)
{
int v2; // eax

v2 = bind(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
exit_error(v2, "bind");
}

canonical_decompiled_code:
void __fastcall func14(int a1, __int64 a2)
{
int v2; // eax

v2 = bind(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
func9(v2, "bind");
}

original_code:
void
bind_socket(int sock, struct addrinfo *addr) {
  int ret = bind(sock, addr->ai_addr, addr->ai_addrlen);
  exit_error(ret, "bind");
}

return_type: void


decompiled_code:
void __fastcall listen_socket(int a1, int a2)
{
int v2; // eax

v2 = listen(a1, a2);
exit_error(v2, "socket");
}

canonical_decompiled_code:
void __fastcall func15(int a1, int a2)
{
int v2; // eax

v2 = listen(a1, a2);
func9(v2, "socket");
}

original_code:
void
listen_socket(int sock, int qlen) {
  int ret = listen(sock, qlen);
  exit_error(ret, "socket");
}

variable_types: qlen int


decompiled_code:
void __fastcall set_reuseaddr(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 1, 2, optval, 4u);
exit_error(v1, "setsockopt REUSEADDR");
}

canonical_decompiled_code:
void __fastcall func16(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 1, 2, optval, 4u);
func9(v1, "setsockopt REUSEADDR");
}

original_code:
void
set_reuseaddr(int sock) {
  int on = 1;
  int ret = setsockopt(sock, 1, 2, &on, sizeof(on));
  exit_error(ret, "setsockopt REUSEADDR");
}

variable_types: on int


decompiled_code:
void __fastcall set_nodelay(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 6, 1, optval, 4u);
exit_error(v1, "setsockopt NODELAY");
}

canonical_decompiled_code:
void __fastcall func17(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 6, 1, optval, 4u);
func9(v1, "setsockopt NODELAY");
}

original_code:
void
set_nodelay(int sock) {
  int on = 1;
  int ret = setsockopt(sock, IPPROTO_TCP, 1, &on, sizeof(on));
  exit_error(ret, "setsockopt NODELAY");
}


decompiled_code:
void __fastcall set_nonblock(int fd)
{
unsigned int v1; // eax
int v2; // eax

v1 = fcntl(fd, 3);
BYTE1(v1) |= 8u;
v2 = fcntl(fd, 4, v1);
exit_error(v2, "NONBLOCK");
}

canonical_decompiled_code:
void __fastcall func18(int fd)
{
unsigned int v1; // eax
int v2; // eax

v1 = fcntl(fd, 3);
BYTE1(v1) |= 8u;
v2 = fcntl(fd, 4, v1);
func9(v2, "NONBLOCK");
}

original_code:
void
set_nonblock(int sock) {
  int flags = fcntl(sock, 3);
  int ret = fcntl(sock, 4, (flags | 04000));
  exit_error(ret, "NONBLOCK");
}

variable_types: flags int


decompiled_code:
__int64 __fastcall listen_to(char *a1)
{
struct addrinfo *v1; // rbp
unsigned int v2; // er12

v1 = get_my_addr(a1);
v2 = get_socket(&v1->ai_flags);
set_reuseaddr(v2);
bind_socket(v2, (__int64)v1);
listen_socket(v2, 2048);
freeaddrinfo(v1);
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func19(char *a1)
{
struct addrinfo *v1; // rbp
unsigned int v2; // er12

v1 = func11(a1);
v2 = func13(&v1->ai_flags);
func16(v2);
func14(v2, (__int64)v1);
func15(v2, 2048);
freeaddrinfo(v1);
return v2;
}

original_code:
int
listen_to (char *port) {
  struct addrinfo *addr = get_my_addr(port);
  int sock = get_socket(addr);
  set_reuseaddr(sock);
  bind_socket(sock, addr);
  listen_socket(sock, 2048);
  freeaddrinfo(addr);
  return sock;
}

canonical_original_code:
int listen_to(char *port) {
  struct addrinfo *addr = get_my_addr(port);
  int sock = get_socket(addr);
  set_reuseaddr(sock);
  bind_socket(sock, addr);
  listen_socket(sock, 2048);
  freeaddrinfo(addr);
  return sock;
}


decompiled_code:
__int64 __fastcall accept_client(int a1)
{
unsigned int v1; // er12

v1 = accept(a1, 0LL, 0LL);
exit_error(v1, "accept");
set_nodelay(v1);
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func20(int a1)
{
unsigned int v1; // er12

v1 = accept(a1, 0LL, 0LL);
func9(v1, "accept");
func17(v1);
return v1;
}

original_code:
int
accept_client(int listen_socket) {
  int sock = accept(listen_socket, ((void *)0), ((void *)0));
  exit_error(sock, "accept");
  set_nodelay(sock);
  return sock;
}


decompiled_code:
__int64 __fastcall connect_addr(int a1, __int64 a2)
{
unsigned int v2; // er12

v2 = connect(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
exit_error(v2, "socket");
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func21(int a1, __int64 a2)
{
unsigned int v2; // er12

v2 = connect(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
func9(v2, "socket");
return v2;
}

original_code:
int
connect_addr(int sock, struct addrinfo *addr) {
  int ret = connect(sock, addr->ai_addr, addr->ai_addrlen);
  exit_error(ret, "socket");
  return ret;
}


decompiled_code:
__int64 __fastcall connect_peer(const char *a1, const char *a2)
{
struct addrinfo *v2; // rbp
unsigned int v3; // er12

v2 = get_peer_addr(a1, a2);
v3 = get_socket(&v2->ai_flags);
connect_addr(v3, (__int64)v2);
set_nodelay(v3);
freeaddrinfo(v2);
return v3;
}

canonical_decompiled_code:
__int64 __fastcall func22(const char *a1, const char *a2)
{
struct addrinfo *v2; // rbp
unsigned int v3; // er12

v2 = func12(a1, a2);
v3 = func13(&v2->ai_flags);
func21(v3, (__int64)v2);
func17(v3);
freeaddrinfo(v2);
return v3;
}

original_code:
int
connect_peer(char *peer, char *port) {
  struct addrinfo *addr = get_peer_addr(peer, port);
  int sock = get_socket(addr);
  connect_addr(sock, addr);
  set_nodelay(sock);
  freeaddrinfo(addr);
  return sock;
}


ping

decompiled_code:
__int64 __fastcall ping(int fd)
{
int v1; // eax
unsigned int v2; // ebx
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = send(fd, "ping123", 8uLL, 0);
exit_error(v1, "send()");
v2 = recv(fd, buf, 8uLL, 0);
exit_error(v2, "recv()");
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func23(int fd)
{
int v1; // eax
unsigned int v2; // ebx
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = send(fd, "ping123", 8uLL, 0);
func9(v1, "send()");
v2 = recv(fd, buf, 8uLL, 0);
func9(v2, "recv()");
return v2;
}

original_code:
int
ping(int sock) {
  char buf[8];
  ssize_t slen = send(sock, "ping123", 8, 0);
  exit_error(slen, "send()");
  ssize_t rlen = recv(sock, buf, 8, 0);
  exit_error(rlen, "recv()");
  return rlen;
}

canonical_original_code:
int ping(int sock) {
  char buf[8];
  long slen = send(sock, "ping123", 8, 0);
  exit_error(slen, "send()");
  long rlen = recv(sock, buf, 8, 0);
  exit_error(rlen, "recv()");
  return rlen;
}

variable_types:
buf
char [8]

variable_types: slen long

variable_types: rlen long


echo

decompiled_code:
__int64 __fastcall echo(int fd)
{
ssize_t v1; // r12
int v3; // eax
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = recv(fd, buf, 8uLL, 0);
exit_error(v1, "recv()");
if ( !v1 )
return 0LL;
v3 = send(fd, buf, v1, 0);
exit_error(v3, "send()");
return (unsigned int)v1;
}

canonical_decompiled_code:
__int64 __fastcall func24(int fd)
{
ssize_t v1; // r12
int v3; // eax
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = recv(fd, buf, 8uLL, 0);
func9(v1, "recv()");
if ( !v1 )
return 0LL;
v3 = send(fd, buf, v1, 0);
func9(v3, "send()");
return (unsigned int)v1;
}

original_code:
int
echo(int sock) {
  char buf[8];
  ssize_t rlen = recv(sock, buf, 8, 0);
  exit_error(rlen, "recv()");
  if (rlen == 0) {
    return 0;
  }
  ssize_t slen = send(sock, buf, rlen, 0);
  exit_error(slen, "send()");
  return rlen;
}

canonical_original_code:
int echo(int sock) {
  char buf[8];
  long rlen = recv(sock, buf, 8, 0);
  exit_error(rlen, "recv()");
  if (rlen == 0) {
    return 0;
  }
  long slen = send(sock, buf, rlen, 0);
  exit_error(slen, "send()");
  return rlen;
}


timestamp

decompiled_code:
double timestamp()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)SLODWORD(v1.tv_sec) * 1000000.0 + (double)SLODWORD(v1.tv_usec);
}

canonical_decompiled_code:
double func25()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)SLODWORD(v1.tv_sec) * 1000000.0 + (double)SLODWORD(v1.tv_usec);
}

original_code:
double
timestamp() {
  struct timeval tp;
  gettimeofday(&tp, ((void *)0));
  return ((double) tp.tv_sec) * 1e6 + (double) tp.tv_usec;
}

variable_types: struct timeval { long tv_sec; long tv_usec; }

return_type: double


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v4; // rbp

if ( argc != 3 )
return usage(argc, argv, envp);
v4 = argv[1];
__isoc99_sscanf();
return client(v4, 0LL);
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v4; // rbp

if ( argc != 3 )
return func8(argc, argv, envp);
v4 = argv[1];
__isoc99_sscanf();
return func7(v4, 0LL);
}

original_code:
int
main(int argc, char** argv) {
  if(argc != 3) {
    return usage(argc, argv);
  }
  char *peer = argv[1];
  char *pings = argv[2];
  int num = 0;
  sscanf(pings, "%d", &num);
  return client(peer, num);
}

canonical_original_code:
int main(int argc, char **argv) {
  if(argc != 3) {
    return usage(argc, argv);
  }
  char *peer = argv[1];
  char *pings = argv[2];
  int num = 0;
  sscanf(pings, "%d", &num);
  return client(peer, num);
}

variable_types: argc int

variable_types:
argv
char **

variable_types:
pings
char *

variable_types: num int


decompiled_code:
int show_help()
{
puts("weighttp <options> <url>");
puts(" -n num number of requests (mandatory)");
puts(" -t num threadcount (default: 1)");
puts(" -c num concurrent clients (default: 1)");
puts(" -k keep alive (default: no)");
puts(" -6 use ipv6 (default: no)");
puts(" -H str add header to request");
puts(" -h show help and exit");
puts(" -v show version and exit\n");
return puts("example: weighttpd -n 10000 -c 10 -t 2 -k -H \"User-Agent: foo\" localhost/index.html\n");
}

canonical_decompiled_code:
int func0()
{
puts("weighttp <options> <url>");
puts(" -n num number of requests (mandatory)");
puts(" -t num threadcount (default: 1)");
puts(" -c num concurrent clients (default: 1)");
puts(" -k keep alive (default: no)");
puts(" -6 use ipv6 (default: no)");
puts(" -H str add header to request");
puts(" -h show help and exit");
puts(" -v show version and exit\n");
return puts("example: weighttpd -n 10000 -c 10 -t 2 -k -H \"User-Agent: foo\" localhost/index.html\n");
}

original_code:
static void show_help(void) {
 printf("weighttp <options> <url>\n");
 printf("  -n num   number of requests    (mandatory)\n");
 printf("  -t num   threadcount           (default: 1)\n");
 printf("  -c num   concurrent clients    (default: 1)\n");
 printf("  -k       keep alive            (default: no)\n");
 printf("  -6       use ipv6              (default: no)\n");
 printf("  -H str   add header to request\n");
 printf("  -h       show help and exit\n");
 printf("  -v       show version and exit\n\n");
 printf("example: weighttpd -n 10000 -c 10 -t 2 -k -H \"User-Agent: foo\" localhost/index.html\n\n");
}

canonical_original_code:
static void show_help() {
 printf("weighttp <options> <url>\n");
 printf("  -n num   number of requests    (mandatory)\n");
 printf("  -t num   threadcount           (default: 1)\n");
 printf("  -c num   concurrent clients    (default: 1)\n");
 printf("  -k       keep alive            (default: no)\n");
 printf("  -6       use ipv6              (default: no)\n");
 printf("  -H str   add header to request\n");
 printf("  -h       show help and exit\n");
 printf("  -v       show version and exit\n\n");
 printf("example: weighttpd -n 10000 -c 10 -t 2 -k -H \"User-Agent: foo\" localhost/index.html\n\n");
}


decompiled_code:
struct addrinfo *__fastcall resolve_host(char *name, unsigned __int16 a2, char a3)
{
struct addrinfo *v5; // rdi
struct addrinfo *v6; // r12
struct addrinfo *v7; // rdx
int v8; // eax
char s[6]; // [rsp+0h] [rbp-56h] BYREF
struct addrinfo *pai; // [rsp+6h] [rbp-50h] BYREF
struct addrinfo req; // [rsp+Eh] [rbp-48h] BYREF

*(_OWORD *)&req.ai_flags = 0LL;
*(_OWORD *)&req.ai_addrlen = 0LL;
req.ai_socktype = 1;
*(_OWORD *)&req.ai_canonname = 0LL;
sprintf(s, "%d", a2);
if ( getaddrinfo(name, s, &req, &pai) )
goto LABEL_14;
v5 = pai;
if ( !pai )
{
LABEL_13:
freeaddrinfo(pai);
LABEL_14:
v6 = 0LL;
fprintf(stderr, "error: could not resolve hostname: %s\n", name);
return v6;
}
v6 = pai;
v7 = 0LL;
while ( 1 )
{
v8 = v6->ai_family;
if ( v8 != 2 )
break;
if ( !a3 )
goto LABEL_10;
LABEL_6:
v7 = v6;
if ( !v6->ai_next )
goto LABEL_13;
v6 = v6->ai_next;
}
if ( !a3 || v8 != 10 )
goto LABEL_6;
LABEL_10:
if ( v6 != pai )
{
v7->ai_next = v6->ai_next;
freeaddrinfo(v5);
v6->ai_next = 0LL;
}
return v6;
}

canonical_decompiled_code:
struct addrinfo *__fastcall func1(char *name, unsigned __int16 a2, char a3)
{
struct addrinfo *v5; // rdi
struct addrinfo *v6; // r12
struct addrinfo *v7; // rdx
int v8; // eax
char s[6]; // [rsp+0h] [rbp-56h] BYREF
struct addrinfo *pai; // [rsp+6h] [rbp-50h] BYREF
struct addrinfo req; // [rsp+Eh] [rbp-48h] BYREF

*(_OWORD *)&req.ai_flags = 0LL;
*(_OWORD *)&req.ai_addrlen = 0LL;
req.ai_socktype = 1;
*(_OWORD *)&req.ai_canonname = 0LL;
sprintf(s, "%d", a2);
if ( getaddrinfo(name, s, &req, &pai) )
goto LABEL_14;
v5 = pai;
if ( !pai )
{
LABEL_13:
freeaddrinfo(pai);
LABEL_14:
v6 = 0LL;
fprintf(stderr, "error: could not resolve hostname: %s\n", name);
return v6;
}
v6 = pai;
v7 = 0LL;
while ( 1 )
{
v8 = v6->ai_family;
if ( v8 != 2 )
break;
if ( !a3 )
goto LABEL_10;
LABEL_6:
v7 = v6;
if ( !v6->ai_next )
goto LABEL_13;
v6 = v6->ai_next;
}
if ( !a3 || v8 != 10 )
goto LABEL_6;
LABEL_10:
if ( v6 != pai )
{
v7->ai_next = v6->ai_next;
freeaddrinfo(v5);
v6->ai_next = 0LL;
}
return v6;
}

original_code:
static struct addrinfo *resolve_host(char *hostname, uint16_t port, uint8_t use_ipv6) {
 int err;
 char port_str[6];
 struct addrinfo hints, *res, *res_first, *res_last;
 memset(&hints, 0, sizeof(hints));
 hints.ai_family = 0;
 hints.ai_socktype = SOCK_STREAM;
 sprintf(port_str, "%d", port);
 err = getaddrinfo(hostname, port_str, &hints, &res_first);
 if (err) {
  fprintf(stderr, "error: " "could not resolve hostname: %s" "\n", hostname);
  return ((void *)0);
 }
 res_last = ((void *)0);
 for (res = res_first; res != ((void *)0); res = res->ai_next) {
  if (res->ai_family == 2 && !use_ipv6)
   break;
  else if (res->ai_family == 10 && use_ipv6)
   break;
  res_last = res;
 }
 if (!res) {
  freeaddrinfo(res_first);
  fprintf(stderr, "error: " "could not resolve hostname: %s" "\n", hostname);
  return ((void *)0);
 }
 if (res != res_first) {
  res_last->ai_next = res->ai_next;
  freeaddrinfo(res_first);
  res->ai_next = ((void *)0);
 }
 return res;
}

canonical_original_code:
static struct addrinfo *resolve_host(char *hostname, unsigned short port, unsigned char use_ipv6) {
 int err;
 char port_str[6];
 struct addrinfo hints; struct addrinfo *res; struct addrinfo *res_first; struct addrinfo *res_last;
 memset(&hints, 0, sizeof(hints));
 hints.ai_family = 0;
 hints.ai_socktype = SOCK_STREAM;
 sprintf(port_str, "%d", port);
 err = getaddrinfo(hostname, port_str, &hints, &res_first);
 if (err) {
  fprintf(stderr, "error: " "could not resolve hostname: %s" "\n", hostname);
  return ((void *)0);
 }
 res_last = ((void *)0);
 for (res = res_first; res != ((void *)0); res = res->ai_next) {
  if (res->ai_family == 2 && !use_ipv6)
   break;
  else if (res->ai_family == 10 && use_ipv6)
   break;
  res_last = res;
 }
 if (!res) {
  freeaddrinfo(res_first);
  fprintf(stderr, "error: " "could not resolve hostname: %s" "\n", hostname);
  return ((void *)0);
 }
 if (res != res_first) {
  res_last->ai_next = res->ai_next;
  freeaddrinfo(res_first);
  res->ai_next = ((void *)0);
 }
 return res;
}

variable_types:
hostname
char *

variable_types:
port
unsigned short

variable_types: err int

variable_types: struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; unsigned int ai_addrlen; struct sockaddr { unsigned short sa_family; char sa_data[14]; } *ai_addr; char *ai_canonname; struct addrinfo *ai_next; }


decompiled_code:
__int64 ev_default_destroy()
{
__int64 v0; // rax

v0 = ev_default_loop(0LL);
return ev_loop_destroy(v0);
}

canonical_decompiled_code:
__int64 func2()
{
__int64 v0; // rax

v0 = ev_default_loop(0LL);
return ev_loop_destroy(v0);
}

original_code: static inline void ev_default_destroy (void) { ev_loop_destroy (ev_default_loop (0)); }

canonical_original_code: static inline void ev_default_destroy() { ev_loop_destroy (ev_default_loop (0)); }


decompiled_code:
__int64 __fastcall str_to_uint64(char *a1)
{
char v1; // al
__int64 v2; // r8
unsigned __int8 v3; // al

v1 = *a1;
v2 = 0LL;
if ( *a1 )
{
while ( 1 )
{
v3 = v1 - 48;
if ( v3 > 9u )
break;
++a1;
v2 = (char)v3 + 10 * v2;
v1 = *a1;
if ( !*a1 )
return v2;
}
v2 = -1LL;
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func3(char *a1)
{
char v1; // al
__int64 v2; // r8
unsigned __int8 v3; // al

v1 = *a1;
v2 = 0LL;
if ( *a1 )
{
while ( 1 )
{
v3 = v1 - 48;
if ( v3 > 9u )
break;
++a1;
v2 = (char)v3 + 10 * v2;
v1 = *a1;
if ( !*a1 )
return v2;
}
v2 = -1LL;
}
return v2;
}

canonical_original_code:
unsigned long str_to_uint64(char *str) {
 unsigned long i;
 for (i = 0; *str; str++) {
  if (*str < '0' || *str > '9')
   return (18446744073709551615UL);
  i *= 10;
  i += *str - '0';
 }
 return i;
}

variable_types:
str
char *

variable_types:
i
unsigned long

return_type: unsigned long


decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er14
char v4; // r13
void *v5; // rbp
char v6; // al
int v7; // er12
__int64 v9; // rax
const char *v10; // rdx
size_t v11; // r15
int v12; // er13
int v13; // ebx
__int64 v14; // rcx
char *v15; // rdi
__int64 v16; // r12
unsigned __int64 v17; // rbp
int v18; // edi
unsigned __int16 v19; // r10
int v20; // eax
__int64 v21; // rax
unsigned int v22; // er14
void *v23; // rcx
pthread_t *v24; // rdi
unsigned int v25; // eax
__int64 v26; // r14
int v27; // ebx
__int64 v28; // rdx
__int64 v29; // r13
__int64 v30; // r12
__int64 v31; // r15
__int64 v32; // rbp
double v33; // xmm0_8
__int64 v34; // rsi
const char *v35; // rdx
_QWORD *ptr; // [rsp+0h] [rbp-118h]
_QWORD *v37; // [rsp+8h] [rbp-110h]
void *v38; // [rsp+10h] [rbp-108h]
unsigned __int16 v39; // [rsp+26h] [rbp-F2h] BYREF
char *name; // [rsp+28h] [rbp-F0h] BYREF
unsigned __int64 v41; // [rsp+30h] [rbp-E8h] BYREF
unsigned __int8 v42; // [rsp+38h] [rbp-E0h]
unsigned __int16 v43; // [rsp+3Ah] [rbp-DEh]
char v44; // [rsp+3Ch] [rbp-DCh]
void *v45; // [rsp+40h] [rbp-D8h]
int v46; // [rsp+48h] [rbp-D0h]
struct addrinfo *ai; // [rsp+50h] [rbp-C8h]
char v48; // [rsp+60h] [rbp-B8h] BYREF
__int64 v49; // [rsp+80h] [rbp-98h]
__int64 v50; // [rsp+88h] [rbp-90h]
__int64 v51; // [rsp+90h] [rbp-88h]
__int64 v52; // [rsp+98h] [rbp-80h]
__int64 v53; // [rsp+A8h] [rbp-70h]
__int64 v54; // [rsp+B0h] [rbp-68h]
__int64 v55; // [rsp+C0h] [rbp-58h]
__int64 v56; // [rsp+C8h] [rbp-50h]
__int64 v57; // [rsp+D0h] [rbp-48h]
__int64 v58; // [rsp+D8h] [rbp-40h]

v3 = 0;
v4 = 0;
v5 = 0LL;
v42 = 1;
v43 = 1;
v41 = 0LL;
v44 = 0;
while ( 2 )
{
v6 = getopt(argc, (char *const *)argv, ":hv6kn:t:c:H:");
if ( v6 != -1 )
{
switch ( v6 )
{
case '6':
v4 = 1;
continue;
case '?':
v7 = 1;
fprintf(stderr, "error: unkown option: -%c\n", (unsigned int)optopt);
show_help();
break;
case 'H':
v5 = realloc(v5, 8LL * (unsigned __int8)v3 + 8);
v9 = (unsigned __int8)v3++;
*((_QWORD *)v5 + v9) = optarg;
continue;
case 'c':
v43 = atoi(optarg);
continue;
case 'h':
show_help();
v7 = 0;
break;
case 'k':
v44 = 1;
continue;
case 'n':
v41 = str_to_uint64(optarg);
continue;
case 't':
v42 = atoi(optarg);
continue;
case 'v':
v7 = 0;
puts("version: X.X.X");
puts("build-date: May 23 2025 04:20:31\n");
break;
default:
continue;
}
return v7;
}
break;
}
v7 = argc - optind;
v10 = "missing url argument\n";
if ( argc - optind <= 0 )
{
LABEL_51:
v7 = 1;
fprintf(stderr, "error: %s\n", v10);
show_help();
return v7;
}
if ( v7 != 1 )
{
v10 = "too many arguments\n";
goto LABEL_51;
}
if ( !v42 )
{
fprintf(stderr, "error: %s\n", "thread count has to be > 0\n");
show_help();
return v7;
}
if ( !v43 )
{
v35 = "number of concurrent clients has to be > 0\n";
goto LABEL_53;
}
if ( !v41 )
{
v35 = "number of requests has to be > 0\n";
goto LABEL_53;
}
if ( v41 == -1LL || v41 < v42 || v43 < v42 || v41 < v43 )
{
v35 = "insane arguments\n";
LABEL_53:
fprintf(stderr, "error: %s\n", v35);
show_help();
return v7;
}
if ( ev_default_loop(0LL) )
{
v45 = forge_request_constprop_0((char *)argv[optind], (void **)&name, &v39);
if ( v45 )
{
v46 = 8;
ai = resolve_host(name, v39, v4);
if ( ai )
{
v11 = v42;
ptr = calloc(v42, 8uLL);
v37 = calloc(v11, 8uLL);
v12 = v43 % (int)v11;
v13 = v41 % v11;
fwrite("starting benchmark...\n", 1uLL, 0x16uLL, stderr);
v14 = 32LL;
v15 = &v48;
while ( v14 )
{
*(_DWORD *)v15 = 0;
v15 += 4;
--v14;
}
ev_time(v15);
v16 = 0LL;
v38 = v5;
while ( v42 > (int)v16 )
{
v17 = v41 / v42;
v18 = v43 / (int)v42;
v19 = v18;
if ( (_WORD)v12 )
{
v20 = (unsigned __int16)v12 / (int)v42;
if ( !v20 )
LOWORD(v20) = 1;
v19 = v18 + v20;
LOWORD(v12) = v12 - v20;
}
if ( (_WORD)v13 )
{
v21 = (unsigned __int16)v13 / (int)v42;
if ( !((unsigned __int16)v13 / (int)v42) )
v21 = 1LL;
v17 = v41 / v42 + v21;
LOWORD(v13) = v13 - v21;
}
v22 = v19;
fprintf(
stderr,
"spawning thread #%d: %u concurrent requests, %lu total requests\n",
(unsigned int)(v16 + 1),
v19,
v17);
v23 = (void *)worker_new((unsigned int)(v16 + 1), &v41, v22, v17);
v37[v16] = v23;
if ( !v23 )
{
v7 = 1;
fprintf(stderr, "error: %s\n", "failed to allocate worker or client");
return v7;
}
v24 = &ptr[v16++];
v25 = pthread_create(v24, 0LL, (void *(*)(void *))&worker_thread, v23);
if ( v25 )
{
v7 = 2;
fprintf(stderr, "error: failed spawning thread (%d)\n", v25);
return v7;
}
}
v26 = 0LL;
v27 = 0;
while ( v42 > (int)v26 )
{
v28 = (unsigned int)pthread_join(ptr[v26], 0LL);
v29 = v37[v26];
if ( (_DWORD)v28 )
{
v7 = 3;
fprintf(stderr, "error: failed joining thread (%d)\n", v28);
return v7;
}
v49 += *(_QWORD *)(v29 + 80);
v30 = 0LL;
v50 += *(_QWORD *)(v29 + 88);
v51 += *(_QWORD *)(v29 + 96);
v52 += *(_QWORD *)(v29 + 104);
v53 += *(_QWORD *)(v29 + 120);
v54 += *(_QWORD *)(v29 + 128);
v55 += *(_QWORD *)(v29 + 144);
v56 += *(_QWORD *)(v29 + 152);
v57 += *(_QWORD *)(v29 + 160);
v58 += *(_QWORD *)(v29 + 168);
while ( *(unsigned __int16 *)(v29 + 40) > (int)v30 )
{
v31 = 0LL;
v32 = *(_QWORD *)(*(_QWORD *)(v29 + 32) + 8 * v30);
while ( 1 )
{
v34 = (unsigned int)(v27 + v31);
if ( (unsigned int)v31 >= *(_DWORD *)(v32 + 32908) )
break;
v33 = *(double *)(*(_QWORD *)(v32 + 32920) + 8 * v31++);
printf("%i %lf\n", v34, v33);
}
++v30;
v27 += v31;
}
++v26;
worker_free(v29);
}
v7 = 0;
ev_default_destroy();
free(ptr);
free(v37);
free(v45);
free(name);
free(v38);
freeaddrinfo(ai);
}
}
}
else
{
v7 = 2;
fprintf(stderr, "error: %s\n", "could not initialize libev\n");
}
return v7;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er14
char v4; // r13
void *v5; // rbp
char v6; // al
int v7; // er12
__int64 v9; // rax
const char *v10; // rdx
size_t v11; // r15
int v12; // er13
int v13; // ebx
__int64 v14; // rcx
char *v15; // rdi
__int64 v16; // r12
unsigned __int64 v17; // rbp
int v18; // edi
unsigned __int16 v19; // r10
int v20; // eax
__int64 v21; // rax
unsigned int v22; // er14
void *v23; // rcx
pthread_t *v24; // rdi
unsigned int v25; // eax
__int64 v26; // r14
int v27; // ebx
__int64 v28; // rdx
__int64 v29; // r13
__int64 v30; // r12
__int64 v31; // r15
__int64 v32; // rbp
double v33; // xmm0_8
__int64 v34; // rsi
const char *v35; // rdx
_QWORD *ptr; // [rsp+0h] [rbp-118h]
_QWORD *v37; // [rsp+8h] [rbp-110h]
void *v38; // [rsp+10h] [rbp-108h]
unsigned __int16 v39; // [rsp+26h] [rbp-F2h] BYREF
char *name; // [rsp+28h] [rbp-F0h] BYREF
unsigned __int64 v41; // [rsp+30h] [rbp-E8h] BYREF
unsigned __int8 v42; // [rsp+38h] [rbp-E0h]
unsigned __int16 v43; // [rsp+3Ah] [rbp-DEh]
char v44; // [rsp+3Ch] [rbp-DCh]
void *v45; // [rsp+40h] [rbp-D8h]
int v46; // [rsp+48h] [rbp-D0h]
struct addrinfo *ai; // [rsp+50h] [rbp-C8h]
char v48; // [rsp+60h] [rbp-B8h] BYREF
__int64 v49; // [rsp+80h] [rbp-98h]
__int64 v50; // [rsp+88h] [rbp-90h]
__int64 v51; // [rsp+90h] [rbp-88h]
__int64 v52; // [rsp+98h] [rbp-80h]
__int64 v53; // [rsp+A8h] [rbp-70h]
__int64 v54; // [rsp+B0h] [rbp-68h]
__int64 v55; // [rsp+C0h] [rbp-58h]
__int64 v56; // [rsp+C8h] [rbp-50h]
__int64 v57; // [rsp+D0h] [rbp-48h]
__int64 v58; // [rsp+D8h] [rbp-40h]

v3 = 0;
v4 = 0;
v5 = 0LL;
v42 = 1;
v43 = 1;
v41 = 0LL;
v44 = 0;
while ( 2 )
{
v6 = getopt(argc, (char *const *)argv, ":hv6kn:t:c:H:");
if ( v6 != -1 )
{
switch ( v6 )
{
case '6':
v4 = 1;
continue;
case '?':
v7 = 1;
fprintf(stderr, "error: unkown option: -%c\n", (unsigned int)optopt);
func0();
break;
case 'H':
v5 = realloc(v5, 8LL * (unsigned __int8)v3 + 8);
v9 = (unsigned __int8)v3++;
*((_QWORD *)v5 + v9) = optarg;
continue;
case 'c':
v43 = atoi(optarg);
continue;
case 'h':
func0();
v7 = 0;
break;
case 'k':
v44 = 1;
continue;
case 'n':
v41 = func3(optarg);
continue;
case 't':
v42 = atoi(optarg);
continue;
case 'v':
v7 = 0;
puts("version: X.X.X");
puts("build-date: May 23 2025 04:20:31\n");
break;
default:
continue;
}
return v7;
}
break;
}
v7 = argc - optind;
v10 = "missing url argument\n";
if ( argc - optind <= 0 )
{
LABEL_51:
v7 = 1;
fprintf(stderr, "error: %s\n", v10);
func0();
return v7;
}
if ( v7 != 1 )
{
v10 = "too many arguments\n";
goto LABEL_51;
}
if ( !v42 )
{
fprintf(stderr, "error: %s\n", "thread count has to be > 0\n");
func0();
return v7;
}
if ( !v43 )
{
v35 = "number of concurrent clients has to be > 0\n";
goto LABEL_53;
}
if ( !v41 )
{
v35 = "number of requests has to be > 0\n";
goto LABEL_53;
}
if ( v41 == -1LL || v41 < v42 || v43 < v42 || v41 < v43 )
{
v35 = "insane arguments\n";
LABEL_53:
fprintf(stderr, "error: %s\n", v35);
func0();
return v7;
}
if ( ev_default_loop(0LL) )
{
v45 = forge_request_constprop_0((char *)argv[optind], (void **)&name, &v39);
if ( v45 )
{
v46 = 8;
ai = func1(name, v39, v4);
if ( ai )
{
v11 = v42;
ptr = calloc(v42, 8uLL);
v37 = calloc(v11, 8uLL);
v12 = v43 % (int)v11;
v13 = v41 % v11;
fwrite("starting benchmark...\n", 1uLL, 0x16uLL, stderr);
v14 = 32LL;
v15 = &v48;
while ( v14 )
{
*(_DWORD *)v15 = 0;
v15 += 4;
--v14;
}
ev_time(v15);
v16 = 0LL;
v38 = v5;
while ( v42 > (int)v16 )
{
v17 = v41 / v42;
v18 = v43 / (int)v42;
v19 = v18;
if ( (_WORD)v12 )
{
v20 = (unsigned __int16)v12 / (int)v42;
if ( !v20 )
LOWORD(v20) = 1;
v19 = v18 + v20;
LOWORD(v12) = v12 - v20;
}
if ( (_WORD)v13 )
{
v21 = (unsigned __int16)v13 / (int)v42;
if ( !((unsigned __int16)v13 / (int)v42) )
v21 = 1LL;
v17 = v41 / v42 + v21;
LOWORD(v13) = v13 - v21;
}
v22 = v19;
fprintf(
stderr,
"spawning thread #%d: %u concurrent requests, %lu total requests\n",
(unsigned int)(v16 + 1),
v19,
v17);
v23 = (void *)worker_new((unsigned int)(v16 + 1), &v41, v22, v17);
v37[v16] = v23;
if ( !v23 )
{
v7 = 1;
fprintf(stderr, "error: %s\n", "failed to allocate worker or client");
return v7;
}
v24 = &ptr[v16++];
v25 = pthread_create(v24, 0LL, (void *(*)(void *))&worker_thread, v23);
if ( v25 )
{
v7 = 2;
fprintf(stderr, "error: failed spawning thread (%d)\n", v25);
return v7;
}
}
v26 = 0LL;
v27 = 0;
while ( v42 > (int)v26 )
{
v28 = (unsigned int)pthread_join(ptr[v26], 0LL);
v29 = v37[v26];
if ( (_DWORD)v28 )
{
v7 = 3;
fprintf(stderr, "error: failed joining thread (%d)\n", v28);
return v7;
}
v49 += *(_QWORD *)(v29 + 80);
v30 = 0LL;
v50 += *(_QWORD *)(v29 + 88);
v51 += *(_QWORD *)(v29 + 96);
v52 += *(_QWORD *)(v29 + 104);
v53 += *(_QWORD *)(v29 + 120);
v54 += *(_QWORD *)(v29 + 128);
v55 += *(_QWORD *)(v29 + 144);
v56 += *(_QWORD *)(v29 + 152);
v57 += *(_QWORD *)(v29 + 160);
v58 += *(_QWORD *)(v29 + 168);
while ( *(unsigned __int16 *)(v29 + 40) > (int)v30 )
{
v31 = 0LL;
v32 = *(_QWORD *)(*(_QWORD *)(v29 + 32) + 8 * v30);
while ( 1 )
{
v34 = (unsigned int)(v27 + v31);
if ( (unsigned int)v31 >= *(_DWORD *)(v32 + 32908) )
break;
v33 = *(double *)(*(_QWORD *)(v32 + 32920) + 8 * v31++);
printf("%i %lf\n", v34, v33);
}
++v30;
v27 += v31;
}
++v26;
worker_free(v29);
}
v7 = 0;
func2();
free(ptr);
free(v37);
free(v45);
free(name);
free(v38);
freeaddrinfo(ai);
}
}
}
else
{
v7 = 2;
fprintf(stderr, "error: %s\n", "could not initialize libev\n");
}
return v7;
}

original_code:
int
main() {
  printf("Echo server started.\n");
  server();
  printf("Echo server finished.\n");
  return 0;
}


server

decompiled_code:
__int64 server()
{
int v0; // ebp
__int64 v1; // r12
__int64 v3; // [rsp+0h] [rbp-48h] BYREF
int v4; // [rsp+8h] [rbp-40h]
__int64 v5; // [rsp+10h] [rbp-38h]
__int64 (__fastcall *v6)(__int64, __int64); // [rsp+18h] [rbp-30h]
int v7; // [rsp+28h] [rbp-20h]
int v8; // [rsp+2Ch] [rbp-1Ch]

v0 = listen_to("8001");
set_nonblock(v0);
v7 = v0;
v1 = ev_default_loop();
v5 = v1;
v3 = 0LL;
v4 = 0;
v6 = event_server;
v8 = 129;
ev_io_start();
ev_loop_constprop_0(v1, &v3);
close(v0);
return 0LL;
}

original_code:
int server() {
  int listen_socket = listen_to("8001");
  int sock = accept_client(listen_socket);
  for (;;) {
    if (echo(sock) == 0) { break; }
  }
  return 0;
}

variable_types: sock int


decompiled_code:
void __fastcall exit_error(int a1, const char *a2)
{
if ( a1 < 0 )
{
perror(a2);
exit(1);
}
}

canonical_decompiled_code:
void __fastcall func11(int a1, const char *a2)
{
if ( a1 < 0 )
{
perror(a2);
exit(1);
}
}

original_code:
void
exit_error(int ret, char *msg) {
  if (ret < 0) {
    perror(msg);
    exit(1);
  }
}

variable_types: ret int

variable_types:
msg
char *


decompiled_code:
void __fastcall exit_gai_error(int a1)
{
const char *v1; // rax

if ( a1 )
{
v1 = gai_strerror(a1);
fprintf(stderr, "%s\n", v1);
exit(1);
}
}

canonical_decompiled_code:
void __fastcall func12(int a1)
{
const char *v1; // rax

if ( a1 )
{
v1 = gai_strerror(a1);
fprintf(stderr, "%s\n", v1);
exit(1);
}
}

original_code:
void
exit_gai_error(int ret) {
  if (ret != 0) {
    fprintf(stderr, "%s\n", gai_strerror(ret));
    exit(1);
  }
}


decompiled_code:
struct addrinfo *__fastcall get_my_addr(char *service)
{
int v1; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_socktype = 0LL;
*(_OWORD *)&req.ai_addr = 0LL;
req.ai_next = 0LL;
*(_QWORD *)&req.ai_flags = 0x200000001LL;
req.ai_socktype = 1;
v1 = getaddrinfo(0LL, service, &req, &pai);
exit_gai_error(v1);
return pai;
}

canonical_decompiled_code:
struct addrinfo *__fastcall func13(char *service)
{
int v1; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_socktype = 0LL;
*(_OWORD *)&req.ai_addr = 0LL;
req.ai_next = 0LL;
*(_QWORD *)&req.ai_flags = 0x200000001LL;
req.ai_socktype = 1;
v1 = getaddrinfo(0LL, service, &req, &pai);
func12(v1);
return pai;
}

original_code:
struct addrinfo *
get_my_addr(char *port) {
  struct addrinfo hints, *addr;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = 2;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0x0001;
  int ret = getaddrinfo(((void *)0), port, &hints, &addr);
  exit_gai_error(ret);
  return addr;
}

variable_types:
port
char *

variable_types: struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; unsigned int ai_addrlen; struct sockaddr { unsigned short sa_family; char sa_data[14]; } *ai_addr; char *ai_canonname; struct addrinfo *ai_next; } *


decompiled_code:
struct addrinfo *__fastcall get_peer_addr(const char *a1, const char *a2)
{
int v2; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_flags = 0LL;
*(_OWORD *)&req.ai_addrlen = 0LL;
*(_OWORD *)&req.ai_canonname = 0LL;
*(_QWORD *)&req.ai_family = 0x100000002LL;
v2 = getaddrinfo(a1, a2, &req, &pai);
exit_gai_error(v2);
return pai;
}

canonical_decompiled_code:
struct addrinfo *__fastcall func14(const char *a1, const char *a2)
{
int v2; // eax
struct addrinfo *pai; // [rsp+8h] [rbp-40h] BYREF
struct addrinfo req; // [rsp+10h] [rbp-38h] BYREF

*(_OWORD *)&req.ai_flags = 0LL;
*(_OWORD *)&req.ai_addrlen = 0LL;
*(_OWORD *)&req.ai_canonname = 0LL;
*(_QWORD *)&req.ai_family = 0x100000002LL;
v2 = getaddrinfo(a1, a2, &req, &pai);
func12(v2);
return pai;
}

original_code:
struct addrinfo*
get_peer_addr(char *peer, char *port) {
  struct addrinfo hints, *addr;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = 2;
  hints.ai_socktype = SOCK_STREAM;
  int ret = getaddrinfo(peer, port, &hints, &addr);
  exit_gai_error(ret);
  return addr;
}

variable_types:
peer
char *


decompiled_code:
__int64 __fastcall get_socket(int *a1)
{
unsigned int v1; // er12

v1 = socket(a1[1], a1[2], a1[3]);
exit_error(v1, "socket");
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func15(int *a1)
{
unsigned int v1; // er12

v1 = socket(a1[1], a1[2], a1[3]);
func11(v1, "socket");
return v1;
}

original_code:
int
get_socket(struct addrinfo *addr) {
  int sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
  exit_error(sock, "socket");
  return sock;
}


decompiled_code:
void __fastcall bind_socket(int a1, __int64 a2)
{
int v2; // eax

v2 = bind(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
exit_error(v2, "bind");
}

canonical_decompiled_code:
void __fastcall func16(int a1, __int64 a2)
{
int v2; // eax

v2 = bind(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
func11(v2, "bind");
}

original_code:
void
bind_socket(int sock, struct addrinfo *addr) {
  int ret = bind(sock, addr->ai_addr, addr->ai_addrlen);
  exit_error(ret, "bind");
}


decompiled_code:
void __fastcall listen_socket(int a1, int a2)
{
int v2; // eax

v2 = listen(a1, a2);
exit_error(v2, "socket");
}

canonical_decompiled_code:
void __fastcall func17(int a1, int a2)
{
int v2; // eax

v2 = listen(a1, a2);
func11(v2, "socket");
}

original_code:
void
listen_socket(int sock, int qlen) {
  int ret = listen(sock, qlen);
  exit_error(ret, "socket");
}

variable_types: qlen int


decompiled_code:
void __fastcall set_reuseaddr(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 1, 2, optval, 4u);
exit_error(v1, "setsockopt REUSEADDR");
}

canonical_decompiled_code:
void __fastcall func18(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 1, 2, optval, 4u);
func11(v1, "setsockopt REUSEADDR");
}

original_code:
void
set_reuseaddr(int sock) {
  int on = 1;
  int ret = setsockopt(sock, 1, 2, &on, sizeof(on));
  exit_error(ret, "setsockopt REUSEADDR");
}

variable_types: on int


decompiled_code:
void __fastcall set_nodelay(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 6, 1, optval, 4u);
exit_error(v1, "setsockopt NODELAY");
}

canonical_decompiled_code:
void __fastcall func19(int a1)
{
int v1; // eax
int optval[3]; // [rsp+Ch] [rbp-Ch] BYREF

optval[0] = 1;
v1 = setsockopt(a1, 6, 1, optval, 4u);
func11(v1, "setsockopt NODELAY");
}

original_code:
void
set_nodelay(int sock) {
  int on = 1;
  int ret = setsockopt(sock, IPPROTO_TCP, 1, &on, sizeof(on));
  exit_error(ret, "setsockopt NODELAY");
}


decompiled_code:
void __fastcall set_nonblock(int fd)
{
unsigned int v1; // eax
int v2; // eax

v1 = fcntl(fd, 3);
BYTE1(v1) |= 8u;
v2 = fcntl(fd, 4, v1);
exit_error(v2, "NONBLOCK");
}

canonical_decompiled_code:
void __fastcall func20(int fd)
{
unsigned int v1; // eax
int v2; // eax

v1 = fcntl(fd, 3);
BYTE1(v1) |= 8u;
v2 = fcntl(fd, 4, v1);
func11(v2, "NONBLOCK");
}

original_code:
void
set_nonblock(int sock) {
  int flags = fcntl(sock, 3);
  int ret = fcntl(sock, 4, (flags | 04000));
  exit_error(ret, "NONBLOCK");
}

variable_types: flags int


decompiled_code:
__int64 __fastcall listen_to(char *a1)
{
struct addrinfo *v1; // rbp
unsigned int v2; // er12

v1 = get_my_addr(a1);
v2 = get_socket(&v1->ai_flags);
set_reuseaddr(v2);
bind_socket(v2, (__int64)v1);
listen_socket(v2, 2048);
freeaddrinfo(v1);
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func21(char *a1)
{
struct addrinfo *v1; // rbp
unsigned int v2; // er12

v1 = func13(a1);
v2 = func15(&v1->ai_flags);
func18(v2);
func16(v2, (__int64)v1);
func17(v2, 2048);
freeaddrinfo(v1);
return v2;
}

original_code:
int
listen_to (char *port) {
  struct addrinfo *addr = get_my_addr(port);
  int sock = get_socket(addr);
  set_reuseaddr(sock);
  bind_socket(sock, addr);
  listen_socket(sock, 2048);
  freeaddrinfo(addr);
  return sock;
}


decompiled_code:
__int64 __fastcall accept_client(int a1)
{
unsigned int v1; // er12

v1 = accept(a1, 0LL, 0LL);
exit_error(v1, "accept");
set_nodelay(v1);
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func22(int a1)
{
unsigned int v1; // er12

v1 = accept(a1, 0LL, 0LL);
func11(v1, "accept");
func19(v1);
return v1;
}

original_code:
int
accept_client(int listen_socket) {
  int sock = accept(listen_socket, ((void *)0), ((void *)0));
  exit_error(sock, "accept");
  set_nodelay(sock);
  return sock;
}


decompiled_code:
__int64 __fastcall connect_addr(int a1, __int64 a2)
{
unsigned int v2; // er12

v2 = connect(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
exit_error(v2, "socket");
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func23(int a1, __int64 a2)
{
unsigned int v2; // er12

v2 = connect(a1, *(const struct sockaddr **)(a2 + 24), *(_DWORD *)(a2 + 16));
func11(v2, "socket");
return v2;
}

original_code:
int
connect_addr(int sock, struct addrinfo *addr) {
  int ret = connect(sock, addr->ai_addr, addr->ai_addrlen);
  exit_error(ret, "socket");
  return ret;
}


decompiled_code:
__int64 __fastcall connect_peer(const char *a1, const char *a2)
{
struct addrinfo *v2; // rbp
unsigned int v3; // er12

v2 = get_peer_addr(a1, a2);
v3 = get_socket(&v2->ai_flags);
connect_addr(v3, (__int64)v2);
set_nodelay(v3);
freeaddrinfo(v2);
return v3;
}

canonical_decompiled_code:
__int64 __fastcall func24(const char *a1, const char *a2)
{
struct addrinfo *v2; // rbp
unsigned int v3; // er12

v2 = func14(a1, a2);
v3 = func15(&v2->ai_flags);
func23(v3, (__int64)v2);
func19(v3);
freeaddrinfo(v2);
return v3;
}

original_code:
int
connect_peer(char *peer, char *port) {
  struct addrinfo *addr = get_peer_addr(peer, port);
  int sock = get_socket(addr);
  connect_addr(sock, addr);
  set_nodelay(sock);
  freeaddrinfo(addr);
  return sock;
}


ping

decompiled_code:
__int64 __fastcall ping(int fd)
{
int v1; // eax
unsigned int v2; // ebx
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = send(fd, "ping123", 8uLL, 0);
exit_error(v1, "send()");
v2 = recv(fd, buf, 8uLL, 0);
exit_error(v2, "recv()");
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func25(int fd)
{
int v1; // eax
unsigned int v2; // ebx
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = send(fd, "ping123", 8uLL, 0);
func11(v1, "send()");
v2 = recv(fd, buf, 8uLL, 0);
func11(v2, "recv()");
return v2;
}

original_code:
int
ping(int sock) {
  char buf[8];
  ssize_t slen = send(sock, "ping123", 8, 0);
  exit_error(slen, "send()");
  ssize_t rlen = recv(sock, buf, 8, 0);
  exit_error(rlen, "recv()");
  return rlen;
}

variable_types:
buf
char [8]

variable_types: slen long

variable_types: rlen long


echo

decompiled_code:
__int64 __fastcall echo(int fd)
{
ssize_t v1; // r12
int v3; // eax
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = recv(fd, buf, 8uLL, 0);
exit_error(v1, "recv()");
if ( !v1 )
return 0LL;
v3 = send(fd, buf, v1, 0);
exit_error(v3, "send()");
return (unsigned int)v1;
}

canonical_decompiled_code:
__int64 __fastcall func26(int fd)
{
ssize_t v1; // r12
int v3; // eax
char buf[32]; // [rsp+8h] [rbp-20h] BYREF

v1 = recv(fd, buf, 8uLL, 0);
func11(v1, "recv()");
if ( !v1 )
return 0LL;
v3 = send(fd, buf, v1, 0);
func11(v3, "send()");
return (unsigned int)v1;
}

original_code:
int
echo(int sock) {
  char buf[8];
  ssize_t rlen = recv(sock, buf, 8, 0);
  exit_error(rlen, "recv()");
  if (rlen == 0) {
    return 0;
  }
  ssize_t slen = send(sock, buf, rlen, 0);
  exit_error(slen, "send()");
  return rlen;
}


timestamp

decompiled_code:
double timestamp()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)SLODWORD(v1.tv_sec) * 1000000.0 + (double)SLODWORD(v1.tv_usec);
}

canonical_decompiled_code:
double func27()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return (double)SLODWORD(v1.tv_sec) * 1000000.0 + (double)SLODWORD(v1.tv_usec);
}

original_code:
double
timestamp() {
  struct timeval tp;
  gettimeofday(&tp, ((void *)0));
  return ((double) tp.tv_sec) * 1e6 + (double) tp.tv_usec;
}

variable_types: struct timeval { long tv_sec; long tv_usec; }


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
puts("Echo server started.");
server("Echo server started.", argv);
puts("Echo server finished.");
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
puts("Echo server started.");
func10("Echo server started.", argv);
puts("Echo server finished.");
return 0;
}

original_code:
int
main() {
  printf("Echo server started.\n");
  server();
  printf("Echo server finished.\n");
  return 0;
}


repo: kbob/kerfburn

decompiled_code:
__int64 open_whatever()
{
__int64 (*v0)(void); // rax

v0 = (__int64 (*)(void))&open_fwsim;
if ( !use_fwsim )
v0 = (__int64 (*)(void))&open_serial;
return v0();
}

canonical_decompiled_code:
__int64 func0()
{
__int64 (*v0)(void); // rax

v0 = (__int64 (*)(void))&open_fwsim;
if ( !use_fwsim )
v0 = (__int64 (*)(void))&open_serial;
return v0();
}

original_code:
static int open_whatever(void)
{
    return (use_fwsim ? open_fwsim : open_serial)();
}

canonical_original_code:
static int open_whatever()
{
    return (use_fwsim ? open_fwsim : open_serial)();
}


decompiled_code:
__int64 close_whatever()
{
__int64 (*v0)(void); // rax

v0 = (__int64 (*)(void))&close_fwsim;
if ( !use_fwsim )
v0 = (__int64 (*)(void))&close_serial;
return v0();
}

canonical_decompiled_code:
__int64 func1()
{
__int64 (*v0)(void); // rax

v0 = (__int64 (*)(void))&close_fwsim;
if ( !use_fwsim )
v0 = (__int64 (*)(void))&close_serial;
return v0();
}

original_code:
static void close_whatever(void)
{
    (use_fwsim ? close_fwsim : close_serial)();
}

canonical_original_code:
static void close_whatever()
{
    (use_fwsim ? close_fwsim : close_serial)();
}


decompiled_code:
__int64 whatever_transmit()
{
__int64 (*v0)(void); // rax

v0 = (__int64 (*)(void))&fwsim_transmit;
if ( !use_fwsim )
v0 = (__int64 (*)(void))&serial_transmit;
return v0();
}

canonical_decompiled_code:
__int64 func2()
{
__int64 (*v0)(void); // rax

v0 = (__int64 (*)(void))&fwsim_transmit;
if ( !use_fwsim )
v0 = (__int64 (*)(void))&serial_transmit;
return v0();
}

original_code:
static int whatever_transmit(const char *buf, size_t count)
{
    return (use_fwsim ? fwsim_transmit : serial_transmit)(buf, count);
}

canonical_original_code:
static int whatever_transmit(char *buf, unsigned long count)
{
    return (use_fwsim ? fwsim_transmit : serial_transmit)(buf, count);
}

variable_types:
buf
char *

variable_types:
count
unsigned long


daemonize

decompiled_code:
__int64 daemonize()
{
unsigned int v0; // er12
int v2; // eax
unsigned int v3; // er12
__pid_t v4; // eax
unsigned int v5; // er12
const char *v6; // r12
char *v7; // rax
const char *v8; // rcx
int stat_loc[3]; // [rsp+Ch] [rbp-Ch] BYREF

v0 = 0;
if ( debug_daemon )
return v0;
v2 = fork();
v3 = v2;
if ( v2 < 0 )
{
v0 = -1;
perror("fork");
return v0;
}
if ( !v2 )
{
v4 = fork();
v5 = v4;
if ( v4 < 0 )
{
perror("forkfork");
exit(1);
}
if ( v4 )
exit(0);
umask(0);
if ( setsid() < 0 )
{
perror("setsid");
exit(1);
}
if ( chdir("/") < 0 )
{
perror("chdir /");
exit(1);
}
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
return v5;
}
if ( waitpid(v2, stat_loc, 0) < 0 )
{
v0 = -1;
perror("waitpid");
return v0;
}
if ( !__OFSUB__((stat_loc[0] & 0x7F) + 1, 1) && (stat_loc[0] & 0x7F) != 0 )
{
v6 = " (core dumped)";
if ( SLOBYTE(stat_loc[0]) >= 0 )
v6 = (const char *)&unk_DDF;
v7 = strsignal(stat_loc[0] & 0x7F);
v8 = v6;
v0 = -1;
fprintf(stderr, "daemon: %s%s\n", v7, v8);
return v0;
}
if ( (stat_loc[0] & 0xFF00) != 0 )
v3 = -1;
return v3;
}

canonical_decompiled_code:
__int64 func3()
{
unsigned int v0; // er12
int v2; // eax
unsigned int v3; // er12
__pid_t v4; // eax
unsigned int v5; // er12
const char *v6; // r12
char *v7; // rax
const char *v8; // rcx
int stat_loc[3]; // [rsp+Ch] [rbp-Ch] BYREF

v0 = 0;
if ( debug_daemon )
return v0;
v2 = fork();
v3 = v2;
if ( v2 < 0 )
{
v0 = -1;
perror("fork");
return v0;
}
if ( !v2 )
{
v4 = fork();
v5 = v4;
if ( v4 < 0 )
{
perror("forkfork");
exit(1);
}
if ( v4 )
exit(0);
umask(0);
if ( setsid() < 0 )
{
perror("setsid");
exit(1);
}
if ( chdir("/") < 0 )
{
perror("chdir /");
exit(1);
}
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
return v5;
}
if ( waitpid(v2, stat_loc, 0) < 0 )
{
v0 = -1;
perror("waitpid");
return v0;
}
if ( !__OFSUB__((stat_loc[0] & 0x7F) + 1, 1) && (stat_loc[0] & 0x7F) != 0 )
{
v6 = " (core dumped)";
if ( SLOBYTE(stat_loc[0]) >= 0 )
v6 = (const char *)&unk_DDF;
v7 = strsignal(stat_loc[0] & 0x7F);
v8 = v6;
v0 = -1;
fprintf(stderr, "daemon: %s%s\n", v7, v8);
return v0;
}
if ( (stat_loc[0] & 0xFF00) != 0 )
v3 = -1;
return v3;
}

original_code:
static int daemonize(void)
{
    if (debug_daemon)
        return 0;
    pid_t child = fork();
    if (child < 0) {
        perror("fork");
        return -1;
    }
    else if (child > 0) {
        int status;
        pid_t pid = waitpid(child, &status, 0);
        if (pid < 0) {
            perror("waitpid");
            return -1;
        }
        if ((((signed char) (((status) & 0x7f) + 1) >> 1) > 0)) {
            fprintf(stderr, "daemon: %s%s\n",
                    strsignal(((status) & 0x7f)),
                    ((status) & 0x80) ? " (core dumped)" : "");
            return -1;
        }
        if ((((status) & 0xff00) >> 8) != 0)
            return -1;
        return child;
    } else {
        pid_t grandchild = fork();
        if (grandchild < 0) {
            perror("forkfork");
            _exit(1);
        }
        if (grandchild > 0)
            _exit(0);
        umask(0);
        if (setsid() < 0)
            perror("setsid"), exit(1);
         if (chdir("/") < 0)
            perror("chdir /"), exit(1);
        freopen("/dev/null", "r", stdin);
        freopen("/dev/null", "w", stdout);
        freopen("/dev/null", "w", stderr);
        return 0;
    }
}

canonical_original_code:
static int daemonize()
{
    if (debug_daemon)
        return 0;
    int child = fork();
    if (child < 0) {
        perror("fork");
        return -1;
    }
    else if (child > 0) {
        int status;
        int pid = waitpid(child, &status, 0);
        if (pid < 0) {
            perror("waitpid");
            return -1;
        }
        if ((((char) (((status) & 0x7f) + 1) >> 1) > 0)) {
            fprintf(stderr, "daemon: %s%s\n",
                    strsignal(((status) & 0x7f)),
                    ((status) & 0x80) ? " (core dumped)" : "");
            return -1;
        }
        if ((((status) & 0xff00) >> 8) != 0)
            return -1;
        return child;
    } else {
        int grandchild = fork();
        if (grandchild < 0) {
            perror("forkfork");
            _exit(1);
        }
        if (grandchild > 0)
            _exit(0);
        umask(0);
        if (setsid() < 0)
            perror("setsid"), exit(1);
         if (chdir("/") < 0)
            perror("chdir /"), exit(1);
        freopen("/dev/null", "r", stdin);
        freopen("/dev/null", "w", stdout);
        freopen("/dev/null", "w", stderr);
        return 0;
    }
}

variable_types: child int

variable_types: status int

variable_types: pid int

variable_types: grandchild int


decompiled_code:
void __fastcall report_daemon_error(char *s)
{
int v1; // ebp
char *v2; // rax

v1 = *_errno_location();
if ( debug_daemon )
perror(s);
v2 = strerror(v1);
syslog(3, "%s: %s", s, v2);
}

canonical_decompiled_code:
void __fastcall func4(char *s)
{
int v1; // ebp
char *v2; // rax

v1 = *_errno_location();
if ( debug_daemon )
perror(s);
v2 = strerror(v1);
syslog(3, "%s: %s", s, v2);
}

original_code:
static void report_daemon_error(const char *label)
{
    int e = (*__errno_location ());
    if (debug_daemon)
        perror(label);
    syslog(3, "%s: %s", label, strerror(e));
}

canonical_original_code:
static void report_daemon_error(char *label)
{
    int e = (*__errno_location ());
    if (debug_daemon)
        perror(label);
    syslog(3, "%s: %s", label, strerror(e));
}

variable_types:
label
char *

variable_types: e int


decompiled_code:
void shutdown_service(void)
{
const char *v0; // rbp
const char *v1; // r12

v0 = (const char *)get_socket_dir();
v1 = (const char *)get_socket_path();
close(listen_socket);
unlink(v1);
rmdir(v0);
}

canonical_decompiled_code:
void func5(void)
{
const char *v0; // rbp
const char *v1; // r12

v0 = (const char *)get_socket_dir();
v1 = (const char *)get_socket_path();
close(listen_socket);
unlink(v1);
rmdir(v0);
}

original_code:
static void shutdown_service(void)
{
    const char *sockdir = get_socket_dir();
    const char *sockpath = get_socket_path();
    (void)close(listen_socket);
    (void)unlink(sockpath);
    (void)rmdir(sockdir);
}

canonical_original_code:
static void shutdown_service()
{
    char *sockdir = get_socket_dir();
    char *sockpath = get_socket_path();
    (void)close(listen_socket);
    (void)unlink(sockpath);
    (void)rmdir(sockdir);
}

variable_types:
sockdir
char *

variable_types:
sockpath
char *


decompiled_code:
int init_service()
{
const char *v0; // r12
const char *v1; // r13
__uid_t v2; // ebp
int v3; // ebp
int v4; // eax
int result; // eax
__int64 v6; // r13
__uid_t v7; // eax
char *v8; // rax
char *v9; // rax
struct sockaddr v10[7]; // [rsp+0h] [rbp-118h] BYREF
struct stat buf; // [rsp+70h] [rbp-A8h] BYREF

v0 = (const char *)get_socket_dir();
v1 = (const char *)get_socket_path();
if ( strlen(v1) > 0x6B )
{
fwrite("port name too long\n", 1uLL, 0x13uLL, stderr);
return -1;
}
if ( lstat(v0, &buf) >= 0 && (buf.st_mode & 0xF000) == 0x4000 )
goto LABEL_9;
unlink(v0);
rmdir(v0);
if ( mkdir(v0, 0x1C0u) < 0 && *_errno_location() != 17 )
{
syslog(3, "mkdir %s failed: %m", v0);
return -1;
}
if ( lstat(v0, &buf) < 0 )
{
syslog(3, "lstat %s failed: %m", v0);
return -1;
}
v2 = buf.st_uid;
if ( buf.st_mode != 16832 )
{
LABEL_18:
v6 = buf.st_mode;
v7 = geteuid();
syslog(3, "%s has wrong user/mode. Expected %d/%0o, got %d/%0o.", v0, v7, 16832LL, v2, v6);
return -1;
}
if ( geteuid() != v2 )
{
v2 = buf.st_uid;
goto LABEL_18;
}
LABEL_9:
unlink(v1);
listen_socket = socket(1, 1, 0);
v3 = listen_socket;
if ( listen_socket < 0 )
{
syslog(3, "listener socket failed: %m");
rmdir(v0);
result = -1;
}
else
{
v10[0].sa_family = 1;
strncpy(v10[0].sa_data, v1, 0x6CuLL);
if ( bind(v3, v10, 0x6Eu) < 0 )
{
syslog(3, "bind to %s failed: %m", v10[0].sa_data);
rmdir(v0);
result = -1;
}
else if ( atexit(shutdown_service) )
{
syslog(3, "atexit failed: %m");
shutdown_service();
result = -1;
}
else if ( listen(v3, 1) )
{
syslog(3, "listen failed: %m");
result = -1;
}
else
{
v4 = pthread_create(&acceptor_thread, 0LL, acceptor_thread_main, 0LL);
if ( v4 )
{
v8 = strerror(v4);
syslog(3, "can't create acceptor thread: %s", v8);
result = -1;
}
else
{
result = pthread_detach(acceptor_thread);
if ( result )
{
v9 = strerror(result);
syslog(3, "can't detach acceptor thread: %s", v9);
result = -1;
}
}
}
}
return result;
}

canonical_decompiled_code:
int func6()
{
const char *v0; // r12
const char *v1; // r13
__uid_t v2; // ebp
int v3; // ebp
int v4; // eax
int result; // eax
__int64 v6; // r13
__uid_t v7; // eax
char *v8; // rax
char *v9; // rax
struct sockaddr v10[7]; // [rsp+0h] [rbp-118h] BYREF
struct stat buf; // [rsp+70h] [rbp-A8h] BYREF

v0 = (const char *)get_socket_dir();
v1 = (const char *)get_socket_path();
if ( strlen(v1) > 0x6B )
{
fwrite("port name too long\n", 1uLL, 0x13uLL, stderr);
return -1;
}
if ( lstat(v0, &buf) >= 0 && (buf.st_mode & 0xF000) == 0x4000 )
goto LABEL_9;
unlink(v0);
rmdir(v0);
if ( mkdir(v0, 0x1C0u) < 0 && *_errno_location() != 17 )
{
syslog(3, "mkdir %s failed: %m", v0);
return -1;
}
if ( lstat(v0, &buf) < 0 )
{
syslog(3, "lstat %s failed: %m", v0);
return -1;
}
v2 = buf.st_uid;
if ( buf.st_mode != 16832 )
{
LABEL_18:
v6 = buf.st_mode;
v7 = geteuid();
syslog(3, "%s has wrong user/mode. Expected %d/%0o, got %d/%0o.", v0, v7, 16832LL, v2, v6);
return -1;
}
if ( geteuid() != v2 )
{
v2 = buf.st_uid;
goto LABEL_18;
}
LABEL_9:
unlink(v1);
listen_socket = socket(1, 1, 0);
v3 = listen_socket;
if ( listen_socket < 0 )
{
syslog(3, "listener socket failed: %m");
rmdir(v0);
result = -1;
}
else
{
v10[0].sa_family = 1;
strncpy(v10[0].sa_data, v1, 0x6CuLL);
if ( bind(v3, v10, 0x6Eu) < 0 )
{
syslog(3, "bind to %s failed: %m", v10[0].sa_data);
rmdir(v0);
result = -1;
}
else if ( atexit(shutdown_service) )
{
syslog(3, "atexit failed: %m");
func5();
result = -1;
}
else if ( listen(v3, 1) )
{
syslog(3, "listen failed: %m");
result = -1;
}
else
{
v4 = pthread_create(&acceptor_thread, 0LL, acceptor_thread_main, 0LL);
if ( v4 )
{
v8 = strerror(v4);
syslog(3, "can't create acceptor thread: %s", v8);
result = -1;
}
else
{
result = pthread_detach(acceptor_thread);
if ( result )
{
v9 = strerror(result);
syslog(3, "can't detach acceptor thread: %s", v9);
result = -1;
}
}
}
}
return result;
}

original_code:
static int init_service(void)
{
    int r = 0;
    const char *sockdir = get_socket_dir();
    const char *sockpath = get_socket_path();
    struct sockaddr_un sun;
    if (strlen(sockpath) >= sizeof sun.sun_path) {
        fprintf(stderr, "port name too long\n");
        return -1;
    }
    struct stat s;
    if (lstat(sockdir, &s) < 0 || !((((s.st_mode)) & 0170000) == (0040000))) {
        (void)unlink(sockdir);
        (void)rmdir(sockdir);
        if (mkdir(sockdir, 0700) < 0 && (*__errno_location ()) != 17) {
            syslog(3, "mkdir %s failed: %m", sockdir);
            return -1;
        }
        if (lstat(sockdir, &s) < 0) {
            syslog(3, "lstat %s failed: %m", sockdir);
            return -1;
        }
        if (s.st_mode != 040700 || s.st_uid != geteuid()) {
            syslog(3,
                   "%s has wrong user/mode.  Expected %d/%0o, got %d/%0o.",
                   sockdir, geteuid(), 040700, s.st_uid, s.st_mode);
            return -1;
        }
    }
    (void)unlink(sockpath);
    listen_socket = socket(1, SOCK_STREAM, 0);
    if (listen_socket < 0) {
        syslog(3, "listener socket failed: %m");
        (void)rmdir(sockdir);
        return -1;
    }
    sun.sun_family = 1;
    strncpy(sun.sun_path, sockpath, sizeof sun.sun_path);
    if (bind(listen_socket, (struct sockaddr *)&sun, sizeof sun) < 0) {
        syslog(3, "bind to %s failed: %m", sun.sun_path);
        (void)rmdir(sockdir);
        return -1;
    }
    if (atexit(shutdown_service) != 0) {
        syslog(3, "atexit failed: %m");
        shutdown_service();
        return -1;
    }
    if (listen(listen_socket, 1)) {
        syslog(3, "listen failed: %m");
        return -1;
    }
    r = pthread_create(&acceptor_thread, ((void *)0), acceptor_thread_main, ((void *)0));
    if (r) {
        syslog(3, "can't create acceptor thread: %s", strerror(r));
        return -1;
    }
    r = pthread_detach(acceptor_thread);
    if (r) {
        syslog(3, "can't detach acceptor thread: %s", strerror(r));
        return -1;
    }
    return 0;
}

canonical_original_code:
static int init_service()
{
    int r = 0;
    char *sockdir = get_socket_dir();
    char *sockpath = get_socket_path();
    struct sockaddr_un sun;
    if (strlen(sockpath) >= sizeof sun.sun_path) {
        fprintf(stderr, "port name too long\n");
        return -1;
    }
    struct stat s;
    if (lstat(sockdir, &s) < 0 || !((((s.st_mode)) & 0170000) == (0040000))) {
        (void)unlink(sockdir);
        (void)rmdir(sockdir);
        if (mkdir(sockdir, 0700) < 0 && (*__errno_location ()) != 17) {
            syslog(3, "mkdir %s failed: %m", sockdir);
            return -1;
        }
        if (lstat(sockdir, &s) < 0) {
            syslog(3, "lstat %s failed: %m", sockdir);
            return -1;
        }
        if (s.st_mode != 040700 || s.st_uid != geteuid()) {
            syslog(3,
                   "%s has wrong user/mode.  Expected %d/%0o, got %d/%0o.",
                   sockdir, geteuid(), 040700, s.st_uid, s.st_mode);
            return -1;
        }
    }
    (void)unlink(sockpath);
    listen_socket = socket(1, SOCK_STREAM, 0);
    if (listen_socket < 0) {
        syslog(3, "listener socket failed: %m");
        (void)rmdir(sockdir);
        return -1;
    }
    sun.sun_family = 1;
    strncpy(sun.sun_path, sockpath, sizeof sun.sun_path);
    if (bind(listen_socket, (struct sockaddr *)&sun, sizeof sun) < 0) {
        syslog(3, "bind to %s failed: %m", sun.sun_path);
        (void)rmdir(sockdir);
        return -1;
    }
    if (atexit(shutdown_service) != 0) {
        syslog(3, "atexit failed: %m");
        shutdown_service();
        return -1;
    }
    if (listen(listen_socket, 1)) {
        syslog(3, "listen failed: %m");
        return -1;
    }
    r = pthread_create(&acceptor_thread, ((void *)0), acceptor_thread_main, ((void *)0));
    if (r) {
        syslog(3, "can't create acceptor thread: %s", strerror(r));
        return -1;
    }
    r = pthread_detach(acceptor_thread);
    if (r) {
        syslog(3, "can't detach acceptor thread: %s", strerror(r));
        return -1;
    }
    return 0;
}

variable_types: r int

variable_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

variable_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec { long tv_sec; long tv_nsec; } st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }

user_defined_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }


decompiled_code:
void accept_client_connection()
{
int v0; // eax
unsigned int v1; // ebp
const char *v2; // rsi
__int64 v3; // rax
__int64 v4; // rbx
unsigned __int8 v5; // [rsp+Bh] [rbp-FDh] BYREF
socklen_t addr_len; // [rsp+Ch] [rbp-FCh] BYREF
char s[112]; // [rsp+10h] [rbp-F8h] BYREF
struct sockaddr addr; // [rsp+80h] [rbp-88h] BYREF
int v9; // [rsp+E8h] [rbp-20h]
__int16 v10; // [rsp+ECh] [rbp-1Ch]

addr_len = 110;
memset(&addr, 0, 0x68uLL);
v9 = 0;
v10 = 0;
v0 = accept(listen_socket, &addr, &addr_len);
if ( v0 < 0 )
{
syslog(4, "client accept failed: %m");
return;
}
v1 = v0;
v2 = "could not read client's first message: %m";
if ( read_line((unsigned int)v0, s, 100LL) <= 0 )
{
LABEL_9:
syslog(4, v2);
close(v1);
return;
}
if ( sscanf(s, "Client Type %c\n", &v5) != 1 )
{
v2 = "client's first message malformed";
goto LABEL_9;
}
switch ( v5 )
{
case 'S':
v3 = 0LL;
break;
case 'R':
v3 = 1LL;
break;
case 'Z':
v3 = 2LL;
break;
default:
syslog(4, "client type %d unknown", v5);
close(v1);
return;
}
v4 = 24 * v3;
syslog(6, "New %s client", (&services)[3 * v3]);
(*(void (__fastcall **)(_QWORD))((char *)&funcs_6CC + v4))(v1);
}

canonical_decompiled_code:
void func7()
{
int v0; // eax
unsigned int v1; // ebp
const char *v2; // rsi
__int64 v3; // rax
__int64 v4; // rbx
unsigned __int8 v5; // [rsp+Bh] [rbp-FDh] BYREF
socklen_t addr_len; // [rsp+Ch] [rbp-FCh] BYREF
char s[112]; // [rsp+10h] [rbp-F8h] BYREF
struct sockaddr addr; // [rsp+80h] [rbp-88h] BYREF
int v9; // [rsp+E8h] [rbp-20h]
__int16 v10; // [rsp+ECh] [rbp-1Ch]

addr_len = 110;
memset(&addr, 0, 0x68uLL);
v9 = 0;
v10 = 0;
v0 = accept(listen_socket, &addr, &addr_len);
if ( v0 < 0 )
{
syslog(4, "client accept failed: %m");
return;
}
v1 = v0;
v2 = "could not read client's first message: %m";
if ( read_line((unsigned int)v0, s, 100LL) <= 0 )
{
LABEL_9:
syslog(4, v2);
close(v1);
return;
}
if ( sscanf(s, "Client Type %c\n", &v5) != 1 )
{
v2 = "client's first message malformed";
goto LABEL_9;
}
switch ( v5 )
{
case 'S':
v3 = 0LL;
break;
case 'R':
v3 = 1LL;
break;
case 'Z':
v3 = 2LL;
break;
default:
syslog(4, "client type %d unknown", v5);
close(v1);
return;
}
v4 = 24 * v3;
syslog(6, "New %s client", (&services)[3 * v3]);
(*(void (__fastcall **)(_QWORD))((char *)&funcs_6CC + v4))(v1);
}

original_code:
static void accept_client_connection(void)
{
    struct sockaddr_un sun;
    socklen_t addrlen = sizeof sun;
    memset(&sun, 0, sizeof sun);
    int client_sock = accept(listen_socket, (struct sockaddr *)&sun, &addrlen);
    if (client_sock < 0) {
        syslog(4, "client accept failed: %m");
        return;
    }
    char line[100];
    ssize_t nr = read_line(client_sock, line, sizeof line);
    if (nr <= 0) {
        syslog(4, "could not read client's first message: %m");
        close(client_sock);
        return;
    }
    char c;
    int ns = sscanf(line, "Client Type %c\n", &c);
    if (ns != 1) {
        syslog(4, "client's first message malformed");
        close(client_sock);
        return;
    }
    for (size_t i = 0; i < service_count; i++) {
        const service *sp = &services[i];
        if (c == sp->s_client_type) {
            syslog(6, "New %s client", sp->s_name);
            (*sp->s_instantiate)(client_sock);
            return;
        }
    }
    syslog(4, "client type %d unknown", c & 0xFF);
    close(client_sock);
}

canonical_original_code:
static void accept_client_connection()
{
    struct sockaddr_un sun;
    unsigned int addrlen = sizeof sun;
    memset(&sun, 0, sizeof sun);
    int client_sock = accept(listen_socket, (struct sockaddr *)&sun, &addrlen);
    if (client_sock < 0) {
        syslog(4, "client accept failed: %m");
        return;
    }
    char line[100];
    long nr = read_line(client_sock, line, sizeof line);
    if (nr <= 0) {
        syslog(4, "could not read client's first message: %m");
        close(client_sock);
        return;
    }
    char c;
    int ns = sscanf(line, "Client Type %c\n", &c);
    if (ns != 1) {
        syslog(4, "client's first message malformed");
        close(client_sock);
        return;
    }
    for (unsigned long i = 0; i < service_count; i++) {
        struct service *sp = &services[i];
        if (c == sp->s_client_type) {
            syslog(6, "New %s client", sp->s_name);
            (*sp->s_instantiate)(client_sock);
            return;
        }
    }
    syslog(4, "client type %d unknown", c & 0xFF);
    close(client_sock);
}

variable_types:
addrlen
unsigned int

variable_types:
line
char [100]

variable_types: nr long

variable_types: c char

variable_types: ns int

variable_types:
i
unsigned long

variable_types: struct service { char *s_name; enum client_type { CT_CONTROLLER=expr, CT_SENDER=expr, CT_RECEIVER=expr, CT_SUSPENDER=expr } s_client_type; void (*s_instantiate)(int sock); } *

user_defined_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

user_defined_types: struct service { char *s_name; enum client_type s_client_type; void (*s_instantiate)(int sock); }


decompiled_code:
void __fastcall __noreturn acceptor_thread_main(void *a1)
{
while ( 1 )
accept_client_connection();
}

canonical_decompiled_code:
void __fastcall __noreturn func8(void *a1)
{
while ( 1 )
func7();
}

original_code:
static void *acceptor_thread_main(void *p)
{
    while (1)
        accept_client_connection();
    return ((void *)0);
}

variable_types:
p
void *

return_type: void *


decompiled_code:
void __fastcall __noreturn send_thread_main(void *a1)
{
unsigned int v1; // eax
int v2; // ebx
void *v3; // rbp
ssize_t v4; // rax
size_t nbytes[4]; // [rsp+8h] [rbp-20h] BYREF

while ( 1 )
{
v1 = await_sender_socket(a1);
nbytes[0] = 0LL;
v2 = v1;
v3 = alloc_data_buf_constprop_0(v1, nbytes);
while ( 1 )
{
v4 = read(v2, v3, nbytes[0]);
if ( v4 < 0 )
{
report_sender_error(3LL, "read from sender failed");
goto LABEL_7;
}
if ( !v4 )
break;
if ( (unsigned int)whatever_transmit(v3) )
report_sender_error(3LL, "serial transmit failed");
}
syslog(6, "EOF on sender");
LABEL_7:
free(v3);
a1 = 0LL;
disconnect_sender(0LL);
}
}

canonical_decompiled_code:
void __fastcall __noreturn func10(void *a1)
{
unsigned int v1; // eax
int v2; // ebx
void *v3; // rbp
ssize_t v4; // rax
size_t nbytes[4]; // [rsp+8h] [rbp-20h] BYREF

while ( 1 )
{
v1 = await_sender_socket(a1);
nbytes[0] = 0LL;
v2 = v1;
v3 = func9(v1, nbytes);
while ( 1 )
{
v4 = read(v2, v3, nbytes[0]);
if ( v4 < 0 )
{
report_sender_error(3LL, "read from sender failed");
goto LABEL_7;
}
if ( !v4 )
break;
if ( (unsigned int)func2(v3) )
report_sender_error(3LL, "serial transmit failed");
}
syslog(6, "EOF on sender");
LABEL_7:
free(v3);
a1 = 0LL;
disconnect_sender(0LL);
}
}

original_code:
static void *send_thread_main(void *p)
{
    while (1) {
        int sock = await_sender_socket();
        size_t buf_size = 0;
        char *buf = alloc_data_buf(sock, &buf_size);
        while (1) {
            ssize_t nr = read(sock, buf, buf_size);
            if (nr < 0) {
                report_sender_error(3, "read from sender failed");
                break;
            }
            if (nr == 0) {
                syslog(6, "EOF on sender");
                break;
            }
            if (whatever_transmit(buf, nr))
                report_sender_error(3, "serial transmit failed");
        }
        free(buf);
        disconnect_sender(((void *)0));
    }
    return ((void *)0);
}

canonical_original_code:
static void *send_thread_main(void *p)
{
    while (1) {
        int sock = await_sender_socket();
        unsigned long buf_size = 0;
        char *buf = alloc_data_buf(sock, &buf_size);
        while (1) {
            long nr = read(sock, buf, buf_size);
            if (nr < 0) {
                report_sender_error(3, "read from sender failed");
                break;
            }
            if (nr == 0) {
                syslog(6, "EOF on sender");
                break;
            }
            if (whatever_transmit(buf, nr))
                report_sender_error(3, "serial transmit failed");
        }
        free(buf);
        disconnect_sender(((void *)0));
    }
    return ((void *)0);
}

variable_types: sock int

variable_types:
buf
char *


decompiled_code:
void *__fastcall receive_thread_main(void *a1)
{
__int64 v1; // rax
_BYTE v3[264]; // [rsp+0h] [rbp-108h] BYREF

do
{
while ( 1 )
{
v1 = whatever_receive_constprop_0((__int64)v3);
if ( v1 <= 0 )
break;
broadcast_to_receivers(v3, v1);
}
}
while ( v1 );
pthread_mutex_lock(&daemon_state);
dword_DCC = 2;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&daemon_state);
return 0LL;
}

canonical_decompiled_code:
void *__fastcall func12(void *a1)
{
__int64 v1; // rax
_BYTE v3[264]; // [rsp+0h] [rbp-108h] BYREF

do
{
while ( 1 )
{
v1 = func11((__int64)v3);
if ( v1 <= 0 )
break;
broadcast_to_receivers(v3, v1);
}
}
while ( v1 );
pthread_mutex_lock(&daemon_state);
dword_DCC = 2;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&daemon_state);
return 0LL;
}

original_code:
static void *receive_thread_main(void *p)
{
    while (1) {
        char buf[256];
        ssize_t nr = whatever_receive(buf, sizeof buf);
        if (nr > 0)
            broadcast_to_receivers(buf, nr);
        if (nr == 0) {
            pthread_mutex_lock(&daemon_state.ds_lock);
            daemon_state.ds_serial = SS_FAILED;
            pthread_cond_signal(&daemon_state.ds_control_cond);
            pthread_mutex_unlock(&daemon_state.ds_lock);
            break;
        }
    }
    return ((void *)0);
}

canonical_original_code:
static void *receive_thread_main(void *p)
{
    while (1) {
        char buf[256];
        long nr = whatever_receive(buf, sizeof buf);
        if (nr > 0)
            broadcast_to_receivers(buf, nr);
        if (nr == 0) {
            pthread_mutex_lock(&daemon_state.ds_lock);
            daemon_state.ds_serial = SS_FAILED;
            pthread_cond_signal(&daemon_state.ds_control_cond);
            pthread_mutex_unlock(&daemon_state.ds_lock);
            break;
        }
    }
    return ((void *)0);
}

variable_types:
buf
char [256]


decompiled_code:
void __fastcall __noreturn run_daemon(__int64 a1)
{
int v1; // eax
struct timeval v2; // [rsp+0h] [rbp-58h] BYREF
struct timespec abstime; // [rsp+10h] [rbp-48h] BYREF

openlog("thruport", 32 * (debug_daemon != 0), 8);
if ( a1 )
{
if ( (unsigned int)init_fwsim(a1) )
goto LABEL_19;
}
else if ( (unsigned int)init_serial() )
{
goto LABEL_19;
}
if ( !init_service() )
{
pthread_mutex_lock(&daemon_state);
while ( 1 )
{
v1 = dword_DCC;
if ( dword_DCC == 2 )
break;
LABEL_10:
if ( dword_DC8 )
{
if ( v1 )
{
destroy_IO_threads_isra_0();
close_whatever();
disconnect_sender("suspended");
dword_DCC = 0;
}
LABEL_7:
pthread_cond_signal(&stru_D98);
goto LABEL_8;
}
if ( !v1 )
{
if ( (unsigned int)open_whatever() )
goto LABEL_13;
goto LABEL_16;
}
LABEL_8:
pthread_cond_wait(&cond, &daemon_state);
}
while ( 1 )
{
destroy_IO_threads_isra_0();
close_whatever();
disconnect_sender("serial port failure");
strcpy((char *)&abstime, "[serial disconnect]\n");
broadcast_to_receivers(&abstime, 20LL);
dword_DCC = 0;
if ( dword_DC8 )
goto LABEL_7;
if ( !(unsigned int)open_whatever() )
break;
LABEL_13:
gettimeofday(&v2, 0LL);
abstime.tv_sec = v2.tv_sec + 1;
abstime.tv_nsec = 1000 * v2.tv_usec;
pthread_cond_timedwait(&cond, &daemon_state, &abstime);
v1 = dword_DCC;
if ( dword_DCC != 2 )
goto LABEL_10;
}
LABEL_16:
create_IO_threads_isra_0();
dword_DCC = 1;
if ( been_here_0 )
{
strcpy((char *)&abstime, "[serial reconnect]\n");
broadcast_to_receivers(&abstime, 19LL);
}
else
{
been_here_0 = 1;
syslog(6, "daemon running");
}
goto LABEL_8;
}
LABEL_19:
exit(1);
}

canonical_decompiled_code:
void __fastcall __noreturn func15(__int64 a1)
{
int v1; // eax
struct timeval v2; // [rsp+0h] [rbp-58h] BYREF
struct timespec abstime; // [rsp+10h] [rbp-48h] BYREF

openlog("thruport", 32 * (debug_daemon != 0), 8);
if ( a1 )
{
if ( (unsigned int)init_fwsim(a1) )
goto LABEL_19;
}
else if ( (unsigned int)init_serial() )
{
goto LABEL_19;
}
if ( !func6() )
{
pthread_mutex_lock(&daemon_state);
while ( 1 )
{
v1 = dword_DCC;
if ( dword_DCC == 2 )
break;
LABEL_10:
if ( dword_DC8 )
{
if ( v1 )
{
func13();
func1();
disconnect_sender("suspended");
dword_DCC = 0;
}
LABEL_7:
pthread_cond_signal(&stru_D98);
goto LABEL_8;
}
if ( !v1 )
{
if ( (unsigned int)func0() )
goto LABEL_13;
goto LABEL_16;
}
LABEL_8:
pthread_cond_wait(&cond, &daemon_state);
}
while ( 1 )
{
func13();
func1();
disconnect_sender("serial port failure");
strcpy((char *)&abstime, "[serial disconnect]\n");
broadcast_to_receivers(&abstime, 20LL);
dword_DCC = 0;
if ( dword_DC8 )
goto LABEL_7;
if ( !(unsigned int)func0() )
break;
LABEL_13:
gettimeofday(&v2, 0LL);
abstime.tv_sec = v2.tv_sec + 1;
abstime.tv_nsec = 1000 * v2.tv_usec;
pthread_cond_timedwait(&cond, &daemon_state, &abstime);
v1 = dword_DCC;
if ( dword_DCC != 2 )
goto LABEL_10;
}
LABEL_16:
func14();
dword_DCC = 1;
if ( been_here_0 )
{
strcpy((char *)&abstime, "[serial reconnect]\n");
broadcast_to_receivers(&abstime, 19LL);
}
else
{
been_here_0 = 1;
syslog(6, "daemon running");
}
goto LABEL_8;
}
LABEL_19:
exit(1);
}

original_code:
__attribute__((noreturn))
static void run_daemon(const char *fwsim)
{
    int option = debug_daemon ? 0x20 : 0;
    openlog("thruport", option, (1<<3));
    if (fwsim) {
        if (init_fwsim(fwsim))
            exit(1);
    } else {
        if (init_serial())
            exit(1);
    }
    if (init_service())
        exit(1);
    pthread_mutex_lock(&daemon_state.ds_lock);
    while (1) {
        _Bool use_timeout = 0;
        if (daemon_state.ds_serial == SS_FAILED) {
            destroy_IO_threads();
            close_whatever();
            disconnect_sender("serial port failure");
            const char msg[] = "[serial disconnect]\n";
            broadcast_to_receivers(msg, sizeof msg - 1);
            daemon_state.ds_serial = SS_CLOSED;
        }
        if (daemon_state.ds_suspender_count) {
            if (daemon_state.ds_serial != SS_CLOSED) {
                destroy_IO_threads();
                close_whatever();
                disconnect_sender("suspended");
                daemon_state.ds_serial = SS_CLOSED;
            }
            pthread_cond_signal(&daemon_state.ds_suspender_cond);
        } else if (daemon_state.ds_serial == SS_CLOSED) {
            if (open_whatever() == 0) {
                create_IO_threads();
                daemon_state.ds_serial = SS_OPEN;
                static _Bool been_here = 0;
                if (!been_here) {
                    been_here = 1;
                    syslog(6, "daemon running");
                } else {
                    const char msg[] = "[serial reconnect]\n";
                    broadcast_to_receivers(msg, sizeof msg - 1);
                }
            } else {
                use_timeout = 1;
            }
        }
        if (use_timeout) {
            struct timeval now;
            struct timespec wake_time;
            gettimeofday(&now, ((void *)0));
            wake_time.tv_sec = now.tv_sec + 1;
            wake_time.tv_nsec = now.tv_usec * 1000;
            pthread_cond_timedwait(&daemon_state.ds_control_cond,
                                   &daemon_state.ds_lock,
                                   &wake_time);
        } else {
            pthread_cond_wait(&daemon_state.ds_control_cond,
                              &daemon_state.ds_lock);
        }
    }
    pthread_mutex_unlock(&daemon_state.ds_lock);
}

canonical_original_code:
static void run_daemon(char *fwsim)
{
    int option = debug_daemon ? 0x20 : 0;
    openlog("thruport", option, (1<<3));
    if (fwsim) {
        if (init_fwsim(fwsim))
            exit(1);
    } else {
        if (init_serial())
            exit(1);
    }
    if (init_service())
        exit(1);
    pthread_mutex_lock(&daemon_state.ds_lock);
    while (1) {
        _Bool use_timeout = 0;
        if (daemon_state.ds_serial == SS_FAILED) {
            destroy_IO_threads();
            close_whatever();
            disconnect_sender("serial port failure");
            char msg[] = "[serial disconnect]\n";
            broadcast_to_receivers(msg, sizeof msg - 1);
            daemon_state.ds_serial = SS_CLOSED;
        }
        if (daemon_state.ds_suspender_count) {
            if (daemon_state.ds_serial != SS_CLOSED) {
                destroy_IO_threads();
                close_whatever();
                disconnect_sender("suspended");
                daemon_state.ds_serial = SS_CLOSED;
            }
            pthread_cond_signal(&daemon_state.ds_suspender_cond);
        } else if (daemon_state.ds_serial == SS_CLOSED) {
            if (open_whatever() == 0) {
                create_IO_threads();
                daemon_state.ds_serial = SS_OPEN;
                static _Bool been_here = 0;
                if (!been_here) {
                    been_here = 1;
                    syslog(6, "daemon running");
                } else {
                    char msg[] = "[serial reconnect]\n";
                    broadcast_to_receivers(msg, sizeof msg - 1);
                }
            } else {
                use_timeout = 1;
            }
        }
        if (use_timeout) {
            struct timeval now;
            struct timespec wake_time;
            gettimeofday(&now, ((void *)0));
            wake_time.tv_sec = now.tv_sec + 1;
            wake_time.tv_nsec = now.tv_usec * 1000;
            pthread_cond_timedwait(&daemon_state.ds_control_cond,
                                   &daemon_state.ds_lock,
                                   &wake_time);
        } else {
            pthread_cond_wait(&daemon_state.ds_control_cond,
                              &daemon_state.ds_lock);
        }
    }
    pthread_mutex_unlock(&daemon_state.ds_lock);
}

variable_types:
fwsim
char *

variable_types: option int

variable_types:
msg
char []

variable_types: struct timeval { long tv_sec; long tv_usec; }

variable_types: struct timespec { long tv_sec; long tv_nsec; }


decompiled_code:
__int64 suspend_daemon()
{
pthread_mutex_lock(&daemon_state);
++dword_DC8;
pthread_cond_signal(&cond);
while ( (unsigned int)dword_DC8 > 1 )
pthread_cond_wait(&stru_D98, &daemon_state);
pthread_mutex_unlock(&daemon_state);
broadcast_to_receivers("\n[suspend]\n", 11LL);
return 0LL;
}

canonical_decompiled_code:
__int64 func16()
{
pthread_mutex_lock(&daemon_state);
++dword_DC8;
pthread_cond_signal(&cond);
while ( (unsigned int)dword_DC8 > 1 )
pthread_cond_wait(&stru_D98, &daemon_state);
pthread_mutex_unlock(&daemon_state);
broadcast_to_receivers("\n[suspend]\n", 11LL);
return 0LL;
}

original_code:
int suspend_daemon(void)
{
    pthread_mutex_lock(&daemon_state.ds_lock);
    ++daemon_state.ds_suspender_count;
    pthread_cond_signal(&daemon_state.ds_control_cond);
    while (daemon_state.ds_suspender_count > 1)
        pthread_cond_wait(&daemon_state.ds_suspender_cond,
                          &daemon_state.ds_lock);
    pthread_mutex_unlock(&daemon_state.ds_lock);
    static const char suspend_msg[] = "\n[suspend]\n";
    broadcast_to_receivers(suspend_msg, sizeof suspend_msg - 1);
    return 0;
}

canonical_original_code:
int suspend_daemon()
{
    pthread_mutex_lock(&daemon_state.ds_lock);
    ++daemon_state.ds_suspender_count;
    pthread_cond_signal(&daemon_state.ds_control_cond);
    while (daemon_state.ds_suspender_count > 1)
        pthread_cond_wait(&daemon_state.ds_suspender_cond,
                          &daemon_state.ds_lock);
    pthread_mutex_unlock(&daemon_state.ds_lock);
    static char suspend_msg[] = "\n[suspend]\n";
    broadcast_to_receivers(suspend_msg, sizeof suspend_msg - 1);
    return 0;
}


decompiled_code:
__int64 resume_daemon()
{
pthread_mutex_lock(&daemon_state);
if ( --dword_DC8 )
{
pthread_cond_signal(&stru_D98);
}
else
{
broadcast_to_receivers(resume_msg_1, 9LL);
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&daemon_state);
return 0LL;
}

canonical_decompiled_code:
__int64 func17()
{
pthread_mutex_lock(&daemon_state);
if ( --dword_DC8 )
{
pthread_cond_signal(&stru_D98);
}
else
{
broadcast_to_receivers(resume_msg_1, 9LL);
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&daemon_state);
return 0LL;
}

original_code:
int resume_daemon(void)
{
    pthread_mutex_lock(&daemon_state.ds_lock);
    if (--daemon_state.ds_suspender_count)
        pthread_cond_signal(&daemon_state.ds_suspender_cond);
    else {
        static char resume_msg[] = "[resume]\n";
        broadcast_to_receivers(resume_msg, sizeof resume_msg - 1);
        pthread_cond_signal(&daemon_state.ds_control_cond);
    }
    pthread_mutex_unlock(&daemon_state.ds_lock);
    return 0;
}

canonical_original_code:
int resume_daemon()
{
    pthread_mutex_lock(&daemon_state.ds_lock);
    if (--daemon_state.ds_suspender_count)
        pthread_cond_signal(&daemon_state.ds_suspender_cond);
    else {
        static char resume_msg[] = "[resume]\n";
        broadcast_to_receivers(resume_msg, sizeof resume_msg - 1);
        pthread_cond_signal(&daemon_state.ds_control_cond);
    }
    pthread_mutex_unlock(&daemon_state.ds_lock);
    return 0;
}


decompiled_code:
__int64 __fastcall start_daemon(char a1, __int64 a2)
{
__int64 result; // rax

use_fwsim = a2 != 0;
debug_daemon = a1;
result = daemonize();
if ( (int)result >= 0 )
{
if ( !(_DWORD)result )
run_daemon(a2);
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func18(char a1, __int64 a2)
{
__int64 result; // rax

use_fwsim = a2 != 0;
debug_daemon = a1;
result = func3();
if ( (int)result >= 0 )
{
if ( !(_DWORD)result )
func15(a2);
result = 0LL;
}
return result;
}

original_code:
int start_daemon(_Bool debug, const char *fwsim)
{
    debug_daemon = debug;
    use_fwsim = fwsim != ((void *)0);
    int r = daemonize();
    if (r < 0)
        return r;
    if (r > 0)
        return 0;
    main_thread = pthread_self();
    run_daemon(fwsim);
}

canonical_original_code:
int start_daemon(_Bool debug, char *fwsim)
{
    debug_daemon = debug;
    use_fwsim = fwsim != ((void *)0);
    int r = daemonize();
    if (r < 0)
        return r;
    if (r > 0)
        return 0;
    main_thread = pthread_self();
    run_daemon(fwsim);
}

variable_types: r int


decompiled_code:
__int64 spawn_daemon()
{
__int64 result; // rax

result = daemonize();
if ( (int)result >= 0 )
{
if ( !(_DWORD)result )
run_daemon(0LL);
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 func19()
{
__int64 result; // rax

result = func3();
if ( (int)result >= 0 )
{
if ( !(_DWORD)result )
func15(0LL);
result = 0LL;
}
return result;
}

original_code:
int spawn_daemon(void)
{
    int r = daemonize();
    if (r < 0)
        return r;
    if (r > 0)
        return 0;
    main_thread = pthread_self();
    run_daemon(((void *)0));
}

canonical_original_code:
int spawn_daemon()
{
    int r = daemonize();
    if (r < 0)
        return r;
    if (r > 0)
        return 0;
    main_thread = pthread_self();
    run_daemon(((void *)0));
}


decompiled_code:
void __noreturn control_main()
{
_assert_fail("false && \"XXX Write me!\"", "front/thruport/main.c", 0x26u, "control_main");
}

canonical_decompiled_code:
void __noreturn func0()
{
_assert_fail("false && \"XXX Write me!\"", "front/thruport/main.c", 0x26u, "control_main");
}

original_code:
static int control_main(int argc, char *argv[])
{
    ((0 && "XXX Write me!") ? (void) (0) : __assert_fail ("false && \"XXX Write me!\"", "front/thruport/main.c", 38, __extension__ __PRETTY_FUNCTION__));
}

variable_types: argc int

variable_types:
argv
char *[]


decompiled_code:
__int64 __fastcall daemon_main(int argc, char **argv)
{
char *v2; // r13
unsigned __int8 v3; // r12
int v4; // eax

v2 = 0LL;
v3 = 0;
optind = 1;
while ( 1 )
{
v4 = getopt_long(argc, argv, "ds:", &daemon_options, 0LL);
if ( v4 == -1 )
break;
if ( v4 == 100 )
{
v3 = 1;
}
else
{
if ( v4 != 115 )
goto LABEL_9;
v2 = optarg;
}
}
if ( optind < argc )
LABEL_9:
usage(stderr);
return start_daemon(v3, v2);
}

canonical_decompiled_code:
__int64 __fastcall func2(int argc, char **argv)
{
char *v2; // r13
unsigned __int8 v3; // r12
int v4; // eax

v2 = 0LL;
v3 = 0;
optind = 1;
while ( 1 )
{
v4 = getopt_long(argc, argv, "ds:", &daemon_options, 0LL);
if ( v4 == -1 )
break;
if ( v4 == 100 )
{
v3 = 1;
}
else
{
if ( v4 != 115 )
goto LABEL_9;
v2 = optarg;
}
}
if ( optind < argc )
LABEL_9:
func1(stderr);
return start_daemon(v3, v2);
}

original_code:
static int daemon_main(int argc, char *argv[])
{
    _Bool debug = 0;
    const char *fwsim = ((void *)0);
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "ds:", daemon_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        case 'd':
            debug = 1;
            break;
        case 's':
            fwsim = optarg;
            break;
        default:
            usage(stderr);
        }
    }
    if (optind < argc)
        usage(stderr);
    return start_daemon(debug, fwsim);
}

canonical_original_code:
static int daemon_main(int argc, char *argv[])
{
    _Bool debug = 0;
    char *fwsim = ((void *)0);
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "ds:", daemon_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        case 'd':
            debug = 1;
            break;
        case 's':
            fwsim = optarg;
            break;
        default:
            usage(stderr);
        }
    }
    if (optind < argc)
        usage(stderr);
    return start_daemon(debug, fwsim);
}

variable_types: c int


decompiled_code:
__int64 __fastcall suspend_main(int a1, char *const *a2)
{
optind = 1;
if ( getopt_long(a1, a2, &byte_303, &suspend_options, 0LL) != -1 || optind >= a1 )
usage(stderr);
return be_suspender(&a2[optind]);
}

canonical_decompiled_code:
__int64 __fastcall func3(int a1, char *const *a2)
{
optind = 1;
if ( getopt_long(a1, a2, &byte_303, &suspend_options, 0LL) != -1 || optind >= a1 )
func1(stderr);
return be_suspender(&a2[optind]);
}

original_code:
static int suspend_main(int argc, char *argv[])
{
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "", suspend_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        default:
            usage(stderr);
        }
    }
    if (optind >= argc)
        usage(stderr);
    const char **prog_argv = (const char **)argv + optind;
    return be_suspender(prog_argv);
}

canonical_original_code:
static int suspend_main(int argc, char *argv[])
{
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "", suspend_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        default:
            usage(stderr);
        }
    }
    if (optind >= argc)
        usage(stderr);
    char **prog_argv = (const char **)argv + optind;
    return be_suspender(prog_argv);
}


decompiled_code:
__int64 __fastcall receive_main(int a1, char *const *a2)
{
optind = 1;
if ( getopt_long(a1, a2, &byte_303, &receive_options, 0LL) != -1 || optind < a1 )
usage(stderr);
return be_receiver();
}

canonical_decompiled_code:
__int64 __fastcall func4(int a1, char *const *a2)
{
optind = 1;
if ( getopt_long(a1, a2, &byte_303, &receive_options, 0LL) != -1 || optind < a1 )
func1(stderr);
return be_receiver();
}

original_code:
static int receive_main(int argc, char *argv[])
{
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "", receive_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        default:
            usage(stderr);
        }
    }
    if (optind < argc)
        usage(stderr);
    return be_receiver();
}


decompiled_code:
__int64 __fastcall send_main(int a1, char *const *a2)
{
char *const *v3; // rdi

optind = 1;
if ( getopt_long(a1, a2, &byte_303, &send_options, 0LL) != -1 )
usage(stderr);
v3 = 0LL;
if ( optind < a1 )
v3 = &a2[optind];
return be_sender(v3);
}

canonical_decompiled_code:
__int64 __fastcall func5(int a1, char *const *a2)
{
char *const *v3; // rdi

optind = 1;
if ( getopt_long(a1, a2, &byte_303, &send_options, 0LL) != -1 )
func1(stderr);
v3 = 0LL;
if ( optind < a1 )
v3 = &a2[optind];
return be_sender(v3);
}

original_code:
static int send_main(int argc, char *argv[])
{
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "", send_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        default:
            usage(stderr);
        }
    }
    const char **files = ((void *)0);
    if (optind < argc)
        files = (const char **)argv + optind;
    return be_sender(files);
}

canonical_original_code:
static int send_main(int argc, char *argv[])
{
    optind = 1;
    while (1) {
        int c = getopt_long(argc, argv, "", send_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        default:
            usage(stderr);
        }
    }
    char **files = ((void *)0);
    if (optind < argc)
        files = (char **)argv + optind;
    return be_sender(files);
}

variable_types:
files
char **


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // er12
const char **v5; // r13
__int64 v6; // rbp
const char *v7; // r14

while ( 1 )
{
v3 = getopt_long(argc, (char *const *)argv, "+ph", &general_options, 0LL);
if ( v3 == -1 )
break;
if ( v3 == 104 )
usage(stdout);
if ( v3 != 112 )
goto LABEL_12;
set_port(optarg);
}
v4 = optind;
if ( optind == argc || !optind )
LABEL_12:
usage(stderr);
v5 = &argv[optind];
v6 = 0LL;
v7 = *v5;
if ( strcmp(*v5, "control") )
{
while ( ++v6 != 5 )
{
if ( !strcmp(v7, (&actions)[2 * v6]) )
return ((__int64 (__fastcall *)(_QWORD, const char **))*(&off_708 + 2 * v6))((unsigned int)(argc - v4), v5);
}
goto LABEL_12;
}
return ((__int64 (__fastcall *)(_QWORD, const char **))*(&off_708 + 2 * v6))((unsigned int)(argc - v4), v5);
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // er12
const char **v5; // r13
__int64 v6; // rbp
const char *v7; // r14

while ( 1 )
{
v3 = getopt_long(argc, (char *const *)argv, "+ph", &general_options, 0LL);
if ( v3 == -1 )
break;
if ( v3 == 104 )
func1(stdout);
if ( v3 != 112 )
goto LABEL_12;
set_port(optarg);
}
v4 = optind;
if ( optind == argc || !optind )
LABEL_12:
func1(stderr);
v5 = &argv[optind];
v6 = 0LL;
v7 = *v5;
if ( strcmp(*v5, "control") )
{
while ( ++v6 != 5 )
{
if ( !strcmp(v7, (&actions)[2 * v6]) )
return ((__int64 (__fastcall *)(_QWORD, const char **))*(&off_708 + 2 * v6))((unsigned int)(argc - v4), v5);
}
goto LABEL_12;
}
return ((__int64 (__fastcall *)(_QWORD, const char **))*(&off_708 + 2 * v6))((unsigned int)(argc - v4), v5);
}

original_code:
int main(int argc, char *argv[])
{
    while (1) {
        int c = getopt_long(argc, argv, "+ph", general_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        case 'p':
            set_port(optarg);
            break;
        case 'h':
            usage(stdout);
        default:
            usage(stderr);
        }
    }
    if (optind == 0 || optind == argc)
        usage(stderr);
    const char *action = argv[optind];
    for (size_t i = 0; i < action_count; i++)
        if (!strcmp(action, actions[i].a_verb))
            return (*actions[i].a_main)(argc - optind, argv + optind);
    usage(stderr);
}

canonical_original_code:
int main(int argc, char *argv[])
{
    while (1) {
        int c = getopt_long(argc, argv, "+ph", general_options, ((void *)0));
        if (c == -1)
            break;
        switch (c) {
        case 'p':
            set_port(optarg);
            break;
        case 'h':
            usage(stdout);
        default:
            usage(stderr);
        }
    }
    if (optind == 0 || optind == argc)
        usage(stderr);
    char *action = argv[optind];
    for (unsigned long i = 0; i < action_count; i++)
        if (!strcmp(action, actions[i].a_verb))
            return (*actions[i].a_main)(argc - optind, argv + optind);
    usage(stderr);
}

variable_types:
action
char *


decompiled_code:
__int64 __fastcall init_fwsim(char *a1)
{
fwsim_command = a1;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func0(char *a1)
{
fwsim_command = a1;
return 0LL;
}

original_code:
int init_fwsim(const char *fwsim)
{
    fwsim_command = fwsim;
    return 0;
}

canonical_original_code:
int init_fwsim(char *fwsim)
{
    fwsim_command = fwsim;
    return 0;
}


decompiled_code:
__int64 open_fwsim()
{
unsigned int v0; // er12
__pid_t v1; // eax
const char *v3; // r12

if ( pipe(recv_pipe) )
{
v0 = -1;
perror("receive pipe");
return v0;
}
v0 = pipe(send_pipe);
if ( v0 )
{
perror("send pipe");
LABEL_9:
v0 = -1;
close(recv_pipe[0]);
close(fd);
return v0;
}
v1 = fork();
pid = v1;
if ( v1 == -1 )
{
perror("fwsim fork");
close(send_pipe[0]);
close(dword_29C);
goto LABEL_9;
}
if ( !v1 )
{
dup2(send_pipe[0], 0);
dup2(fd, 1);
close(send_pipe[0]);
close(dword_29C);
close(recv_pipe[0]);
close(fd);
v3 = fwsim_command;
execlp(fwsim_command, fwsim_command, 0LL);
perror(v3);
exit(1);
}
close(send_pipe[0]);
close(fd);
send_pipe[0] = -1;
fd = -1;
return v0;
}

canonical_decompiled_code:
__int64 func1()
{
unsigned int v0; // er12
__pid_t v1; // eax
const char *v3; // r12

if ( pipe(recv_pipe) )
{
v0 = -1;
perror("receive pipe");
return v0;
}
v0 = pipe(send_pipe);
if ( v0 )
{
perror("send pipe");
LABEL_9:
v0 = -1;
close(recv_pipe[0]);
close(fd);
return v0;
}
v1 = fork();
pid = v1;
if ( v1 == -1 )
{
perror("fwsim fork");
close(send_pipe[0]);
close(dword_29C);
goto LABEL_9;
}
if ( !v1 )
{
dup2(send_pipe[0], 0);
dup2(fd, 1);
close(send_pipe[0]);
close(dword_29C);
close(recv_pipe[0]);
close(fd);
v3 = fwsim_command;
execlp(fwsim_command, fwsim_command, 0LL);
perror(v3);
exit(1);
}
close(send_pipe[0]);
close(fd);
send_pipe[0] = -1;
fd = -1;
return v0;
}

original_code:
int open_fwsim(void)
{
    if (pipe(recv_pipe)) {
        perror("receive pipe");
        return -1;
    }
    if (pipe(send_pipe)) {
        perror("send pipe");
        close(recv_pipe[0]);
        close(recv_pipe[1]);
        return -1;
    }
    pid = fork();
    if (pid == -1) {
        perror("fwsim fork");
        close(send_pipe[0]);
        close(send_pipe[1]);
        close(recv_pipe[0]);
        close(recv_pipe[1]);
        return -1;
    }
    if (pid == 0) {
        dup2(send_pipe[0], 0);
        dup2(recv_pipe[1], 1);
        close(send_pipe[0]);
        close(send_pipe[1]);
        close(recv_pipe[0]);
        close(recv_pipe[1]);
        execlp(fwsim_command, fwsim_command, ((void *)0));
        perror(fwsim_command);
        _exit(1);
    }
    close(send_pipe[0]);
    close(recv_pipe[1]);
    send_pipe[0] = -1;
    recv_pipe[1] = -1;
    return 0;
}

canonical_original_code:
int open_fwsim()
{
    if (pipe(recv_pipe)) {
        perror("receive pipe");
        return -1;
    }
    if (pipe(send_pipe)) {
        perror("send pipe");
        close(recv_pipe[0]);
        close(recv_pipe[1]);
        return -1;
    }
    pid = fork();
    if (pid == -1) {
        perror("fwsim fork");
        close(send_pipe[0]);
        close(send_pipe[1]);
        close(recv_pipe[0]);
        close(recv_pipe[1]);
        return -1;
    }
    if (pid == 0) {
        dup2(send_pipe[0], 0);
        dup2(recv_pipe[1], 1);
        close(send_pipe[0]);
        close(send_pipe[1]);
        close(recv_pipe[0]);
        close(recv_pipe[1]);
        execlp(fwsim_command, fwsim_command, ((void *)0));
        perror(fwsim_command);
        _exit(1);
    }
    close(send_pipe[0]);
    close(recv_pipe[1]);
    send_pipe[0] = -1;
    recv_pipe[1] = -1;
    return 0;
}