decompiled_code:
__int64 __fastcall rsh_register_fs(void *a1, const char *a2, void *a3)
{
const char *v3; // rbx
__int64 v5; // rax
size_t v6; // rax
char *v7; // rax
char *v8; // rbp
size_t v9; // rax

if ( *(&ptr + 2) )
return 0xFFFFFFFFLL;
v3 = a2;
*(&ptr + 2) = a1;
LODWORD(v5) = strlen(a2);
if ( (int)v5 >= 0 )
{
v5 = (int)v5;
while ( a2[v5] != 47 )
{
if ( (int)--v5 < 0 )
goto LABEL_8;
}
v3 = &a2[v5 + 1];
}
LABEL_8:
v6 = strlen(v3);
v7 = (char *)malloc(v6 + 1);
v8 = v7;
rsh_root = v7;
if ( !v7 )
return 0xFFFFFFFFLL;
*v7 = 47;
v9 = strlen(v3);
memcpy(v8 + 1, v3, v9);
*(&ptr + 3) = a3;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func2(void *a1, const char *a2, void *a3)
{
const char *v3; // rbx
__int64 v5; // rax
size_t v6; // rax
char *v7; // rax
char *v8; // rbp
size_t v9; // rax

if ( *(&ptr + 2) )
return 0xFFFFFFFFLL;
v3 = a2;
*(&ptr + 2) = a1;
LODWORD(v5) = strlen(a2);
if ( (int)v5 >= 0 )
{
v5 = (int)v5;
while ( a2[v5] != 47 )
{
if ( (int)--v5 < 0 )
goto LABEL_8;
}
v3 = &a2[v5 + 1];
}
LABEL_8:
v6 = strlen(v3);
v7 = (char *)malloc(v6 + 1);
v8 = v7;
rsh_root = v7;
if ( !v7 )
return 0xFFFFFFFFLL;
*v7 = 47;
v9 = strlen(v3);
memcpy(v8 + 1, v3, v9);
*(&ptr + 3) = a3;
return 0LL;
}

original_code:
int rsh_register_fs(struct rsh_io_ops *fops, char *name, void *driver){
  int i;
  char *leaf_name;
  if ( fs.fops != ((void *)0) ){
    return -1;
  }
  fs.fops = fops;
  leaf_name = name;
  for ( i = strlen(name); i >= 0; i--){
    if ( name[i] == '/' ){
      leaf_name = &(name[i+1]);
      break;
    }
  }
  rsh_root = (char *)malloc( strlen(leaf_name) + 1 );
  if ( ! rsh_root )
    return -1;
  rsh_root[0] = '/';
  memcpy(rsh_root+1, leaf_name, strlen(leaf_name));
  fs.driver = driver;
  return 0;
}

variable_types: struct rsh_io_ops { long (*read)(struct rsh_file { int used; int references; long offset; char *path; struct rsh_io_ops *fops; unsigned int mode; long size; long block_size; long blocks; long access_time; void *local; } *file, void *buf, unsigned long count); long (*write)(struct rsh_file *file, void *buf, unsigned long count); int (*open)(struct rsh_file *file, char *pathname, int flags); int (*close)(struct rsh_file *file); int (*readdir)(struct rsh_file *file, void *buf, unsigned long space); int (*mkdir)(char *path); int (*unlink)(char *path); } *

variable_types:
name
char *

variable_types:
driver
void *

variable_types: i int

user_defined_types: struct rsh_io_ops { long (*read)(struct rsh_file *file, void *buf, unsigned long count); long (*write)(struct rsh_file *file, void *buf, unsigned long count); int (*open)(struct rsh_file *file, char *pathname, int flags); int (*close)(struct rsh_file *file); int (*readdir)(struct rsh_file *file, void *buf, unsigned long space); int (*mkdir)(char *path); int (*unlink)(char *path); }


repo: imnotlistening/rsh

decompiled_code:
int __fastcall rsh_path_location(char *s1)
{
const char *v1; // rbp
size_t v2; // rax
int result; // eax

v1 = rsh_root;
v2 = strlen(rsh_root);
result = strncmp(s1, v1, v2);
if ( result )
{
result = 1;
if ( *s1 != 47 )
result = native;
}
return result;
}

canonical_decompiled_code:
int __fastcall func7(char *s1)
{
const char *v1; // rbp
size_t v2; // rax
int result; // eax

v1 = rsh_root;
v2 = strlen(rsh_root);
result = strncmp(s1, v1, v2);
if ( result )
{
result = 1;
if ( *s1 != 47 )
result = native;
}
return result;
}

original_code:
int rsh_path_location(char *path){
  if ( strncmp(path, rsh_root, strlen(rsh_root)) == 0 )
    return 0;
  if ( path[0] == '/' )
    return 1;
  return native;
}

variable_types:
path
char *

return_type: int


decompiled_code:
__int64 __fastcall rsh_read(int a1)
{
__int64 (*v1)(void); // rcx
__int64 result; // rax

if ( (a1 & 0x8000) != 0 && *((_DWORD *)ptr + 20 * (int)(a1 & 0xFFFF7FFF)) )
{
v1 = *(__int64 (**)(void))*(&ptr + 2);
result = 0LL;
if ( v1 )
result = v1();
}
else
{
*_errno_location() = 9;
result = -1LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(int a1)
{
__int64 (*v1)(void); // rcx
__int64 result; // rax

if ( (a1 & 0x8000) != 0 && *((_DWORD *)ptr + 20 * (int)(a1 & 0xFFFF7FFF)) )
{
v1 = *(__int64 (**)(void))*(&ptr + 2);
result = 0LL;
if ( v1 )
result = v1();
}
else
{
*_errno_location() = 9;
result = -1LL;
}
return result;
}

original_code:
ssize_t rsh_read(int fd, void *buf, size_t count){
  if ( ! ( fd & 0x8000 ) )
    return read(fd, buf, count);
  else
    return _rsh_read(fd, buf, count);
}

canonical_original_code:
long rsh_read(int fd, void *buf, unsigned long count){
  if ( ! ( fd & 0x8000 ) )
    return read(fd, buf, count);
  else
    return _rsh_read(fd, buf, count);
}

variable_types: fd int

variable_types:
buf
void *

variable_types:
count
unsigned long

return_type: long


decompiled_code:
__int64 __fastcall rsh_write(int a1)
{
__int64 (*v1)(void); // rcx
__int64 result; // rax

if ( (a1 & 0x8000) != 0 && *((_DWORD *)ptr + 20 * (int)(a1 & 0xFFFF7FFF)) )
{
v1 = (__int64 (*)(void))*((_QWORD *)*(&ptr + 2) + 1);
result = 0LL;
if ( v1 )
result = v1();
}
else
{
*_errno_location() = 9;
result = -1LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func9(int a1)
{
__int64 (*v1)(void); // rcx
__int64 result; // rax

if ( (a1 & 0x8000) != 0 && *((_DWORD *)ptr + 20 * (int)(a1 & 0xFFFF7FFF)) )
{
v1 = (__int64 (*)(void))*((_QWORD *)*(&ptr + 2) + 1);
result = 0LL;
if ( v1 )
result = v1();
}
else
{
*_errno_location() = 9;
result = -1LL;
}
return result;
}

original_code:
ssize_t rsh_write(int fd, const void *buf, size_t count){
  if ( ! ( fd & 0x8000 ) )
    return write(fd, buf, count);
  else
    return _rsh_write(fd, buf, count);
}

canonical_original_code:
long rsh_write(int fd, void *buf, unsigned long count){
  if ( ! ( fd & 0x8000 ) )
    return write(fd, buf, count);
  else
    return _rsh_write(fd, buf, count);
}


decompiled_code:
__int64 rsh_dup2()
{
return 0xFFFFFFFFLL;
}

canonical_decompiled_code:
__int64 func10()
{
return 0xFFFFFFFFLL;
}

original_code:
int rsh_dup2(int oldfd, int newfd){
  return -1;
}

variable_types: oldfd int

variable_types: newfd int


original_code:
int rsh_open(const char *pathname, int flags, mode_t mode){
  if ( rsh_native_path(pathname) ){
    return open(pathname, flags, mode);
  } else {
    return _rsh_open(pathname, flags, mode);
  }
}

canonical_original_code:
int rsh_open(char *pathname, int flags, unsigned int mode){
  if ( rsh_native_path(pathname) ){
    return open(pathname, flags, mode);
  } else {
    return _rsh_open(pathname, flags, mode);
  }
}

variable_types:
pathname
char *

variable_types: flags int

variable_types:
mode
unsigned int


original_code:
int rsh_close(int fd){
  if ( ! ( fd & 0x8000 ) )
    return close(fd);
  else
    return _rsh_close(fd);
}


decompiled_code:
void *__fastcall rsh_readdir(int a1)
{
int v1; // ebx
int *v2; // rax
_DWORD *v3; // rdi
__int64 (__fastcall *v4)(_DWORD *, void *, __int64); // rcx
int v5; // eax
int v6; // esi
void *result; // rax

v1 = a1;
v2 = _errno_location();
*v2 = 0;
if ( (a1 & 0x8000) == 0 )
{
*v2 = 9;
return 0LL;
}
BYTE1(v1) = BYTE1(a1) & 0x7F;
v3 = (char *)ptr + 80 * v1;
if ( !*v3 )
{
*v2 = 9;
return 0LL;
}
v4 = (__int64 (__fastcall *)(_DWORD *, void *, __int64))*((_QWORD *)*(&ptr + 2) + 4);
if ( !v4 )
{
*v2 = 38;
return 0LL;
}
if ( !dirs_len )
{
if ( almost_done || (v5 = v4(v3, &dirs, 2240LL), (dirs_len = v5) == 0) )
{
diri = 0;
dirs_len = 0;
almost_done = 0;
return 0LL;
}
if ( v5 <= 7 )
almost_done = 1;
}
v6 = diri++;
qmemcpy(&dir_entry, (char *)&dirs + 280 * v6, 0x118uLL);
result = &dir_entry;
if ( diri >= dirs_len )
{
diri = 0;
dirs_len = 0;
}
return result;
}

canonical_decompiled_code:
void *__fastcall func13(int a1)
{
int v1; // ebx
int *v2; // rax
_DWORD *v3; // rdi
__int64 (__fastcall *v4)(_DWORD *, void *, __int64); // rcx
int v5; // eax
int v6; // esi
void *result; // rax

v1 = a1;
v2 = _errno_location();
*v2 = 0;
if ( (a1 & 0x8000) == 0 )
{
*v2 = 9;
return 0LL;
}
BYTE1(v1) = BYTE1(a1) & 0x7F;
v3 = (char *)ptr + 80 * v1;
if ( !*v3 )
{
*v2 = 9;
return 0LL;
}
v4 = (__int64 (__fastcall *)(_DWORD *, void *, __int64))*((_QWORD *)*(&ptr + 2) + 4);
if ( !v4 )
{
*v2 = 38;
return 0LL;
}
if ( !dirs_len )
{
if ( almost_done || (v5 = v4(v3, &dirs, 2240LL), (dirs_len = v5) == 0) )
{
diri = 0;
dirs_len = 0;
almost_done = 0;
return 0LL;
}
if ( v5 <= 7 )
almost_done = 1;
}
v6 = diri++;
qmemcpy(&dir_entry, (char *)&dirs + 280 * v6, 0x118uLL);
result = &dir_entry;
if ( diri >= dirs_len )
{
diri = 0;
dirs_len = 0;
}
return result;
}

original_code:
struct dirent *rsh_readdir(int dfd){
  if ( ! ( dfd & 0x8000 ) )
    return ((void *)0);
  else
    return _rsh_readdir(dfd);
}

variable_types: dfd int

return_type: struct dirent { unsigned long d_ino; long d_off; unsigned short d_reclen; unsigned char d_type; char d_name[256]; } *


original_code:
int rsh_fstat(int fd, struct stat *buf){
  if ( ! ( fd & 0x8000 ) )
    return fstat(fd, buf);
  else
    return _rsh_fstat(fd, buf);
}

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:
__int64 __fastcall rsh_chdir(char *a1)
{
char *v1; // rbp
size_t v2; // rax
char *v3; // rbx
size_t v4; // rax
size_t v5; // rax
int v6; // eax
unsigned int v7; // er12
_BYTE v9[168]; // [rsp+0h] [rbp-A8h] BYREF

if ( *a1 == 47 )
v1 = strdup(a1);
else
v1 = rsh_fs_rel2abs(a1);
if ( !v1 )
{
*_errno_location() = 12;
return 0xFFFFFFFFLL;
}
rsh_fs_interpolate(v1);
v2 = strlen(v1);
v3 = (char *)malloc(v2 + 2);
v4 = strlen(v1);
memcpy(v3, v1, v4 + 1);
v5 = strlen(v3);
if ( v3[v5 - 1] != 47 )
{
v3[v5 + 1] = 0;
v3[strlen(v3)] = 47;
}
v6 = rsh_open(v3, 0);
v7 = v6;
if ( v6 < 0 || (int)rsh_fstat(v6, (__int64)v9) < 0 )
goto LABEL_15;
rsh_close(v7);
if ( (v9[25] & 0x40) == 0 )
{
*_errno_location() = 20;
LABEL_15:
free(v3);
free(v1);
return 0xFFFFFFFFLL;
}
if ( rsh_cwd_alloc )
free(rsh_cwd);
rsh_cwd = v3;
rsh_cwd_alloc = 1;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func15(char *a1)
{
char *v1; // rbp
size_t v2; // rax
char *v3; // rbx
size_t v4; // rax
size_t v5; // rax
int v6; // eax
unsigned int v7; // er12
_BYTE v9[168]; // [rsp+0h] [rbp-A8h] BYREF

if ( *a1 == 47 )
v1 = strdup(a1);
else
v1 = func4(a1);
if ( !v1 )
{
*_errno_location() = 12;
return 0xFFFFFFFFLL;
}
func5(v1);
v2 = strlen(v1);
v3 = (char *)malloc(v2 + 2);
v4 = strlen(v1);
memcpy(v3, v1, v4 + 1);
v5 = strlen(v3);
if ( v3[v5 - 1] != 47 )
{
v3[v5 + 1] = 0;
v3[strlen(v3)] = 47;
}
v6 = func11(v3, 0);
v7 = v6;
if ( v6 < 0 || (int)func14(v6, (__int64)v9) < 0 )
goto LABEL_15;
func12(v7);
if ( (v9[25] & 0x40) == 0 )
{
*_errno_location() = 20;
LABEL_15:
free(v3);
free(v1);
return 0xFFFFFFFFLL;
}
if ( rsh_cwd_alloc )
free(rsh_cwd);
rsh_cwd = v3;
rsh_cwd_alloc = 1;
return 0LL;
}

original_code:
int rsh_chdir(const char *dir){
  if ( native )
    return chdir(dir);
  else
    return _rsh_chdir(dir);
}

canonical_original_code:
int rsh_chdir(char *dir){
  if ( native )
    return chdir(dir);
  else
    return _rsh_chdir(dir);
}

variable_types:
dir
char *


decompiled_code:
__int64 __fastcall rsh_mkdir(char *a1)
{
char *v1; // rdi
__int64 (__fastcall *v2)(char *); // rax

v1 = rsh_fs_rel2abs(a1);
v2 = (__int64 (__fastcall *)(char *))*((_QWORD *)*(&ptr + 2) + 5);
if ( v2 )
return v2(v1);
*_errno_location() = 1;
return 0xFFFFFFFFLL;
}

canonical_decompiled_code:
__int64 __fastcall func16(char *a1)
{
char *v1; // rdi
__int64 (__fastcall *v2)(char *); // rax

v1 = func4(a1);
v2 = (__int64 (__fastcall *)(char *))*((_QWORD *)*(&ptr + 2) + 5);
if ( v2 )
return v2(v1);
*_errno_location() = 1;
return 0xFFFFFFFFLL;
}

original_code:
int rsh_mkdir(const char *path, mode_t mode){
  if ( native )
    return mkdir(path, mode);
  else
    return _rsh_mkdir(path);
}

canonical_original_code:
int rsh_mkdir(char *path, unsigned int mode){
  if ( native )
    return mkdir(path, mode);
  else
    return _rsh_mkdir(path);
}


decompiled_code:
__int64 __fastcall rsh_unlink(char *a1)
{
char *v1; // rdi
__int64 (__fastcall *v2)(char *); // rdx
__int64 result; // rax

v1 = rsh_fs_rel2abs(a1);
v2 = (__int64 (__fastcall *)(char *))*((_QWORD *)*(&ptr + 2) + 6);
result = 0LL;
if ( v2 )
result = v2(v1);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func17(char *a1)
{
char *v1; // rdi
__int64 (__fastcall *v2)(char *); // rdx
__int64 result; // rax

v1 = func4(a1);
v2 = (__int64 (__fastcall *)(char *))*((_QWORD *)*(&ptr + 2) + 6);
result = 0LL;
if ( v2 )
result = v2(v1);
return result;
}

original_code:
int rsh_unlink(const char *path){
  if ( native )
    return unlink(path);
  else
    return _rsh_unlink(path);
}

canonical_original_code:
int rsh_unlink(char *path){
  if ( native )
    return unlink(path);
  else
    return _rsh_unlink(path);
}


decompiled_code:
__int64 builtin_dumpfds()
{
__int64 v0; // rbx
unsigned int v1; // ebp

if ( *((int *)&ptr + 2) <= 0 )
return 0LL;
v0 = 0LL;
v1 = 0;
do
{
if ( *(_DWORD *)((char *)ptr + v0) )
{
printf("FD: %d\n", v1);
printf(" references: %d\n", *(unsigned int *)((char *)ptr + v0 + 4));
printf(" offset: %d\n", *(_QWORD *)((char *)ptr + v0 + 8));
printf(" path: %s\n", *(const char **)((char *)ptr + v0 + 16));
printf(" size: %d\n", *(_QWORD *)((char *)ptr + v0 + 40));
}
++v1;
v0 += 80LL;
}
while ( *((_DWORD *)&ptr + 2) > (signed int)v1 );
return 0LL;
}

canonical_decompiled_code:
__int64 func18()
{
__int64 v0; // rbx
unsigned int v1; // ebp

if ( *((int *)&ptr + 2) <= 0 )
return 0LL;
v0 = 0LL;
v1 = 0;
do
{
if ( *(_DWORD *)((char *)ptr + v0) )
{
printf("FD: %d\n", v1);
printf(" references: %d\n", *(unsigned int *)((char *)ptr + v0 + 4));
printf(" offset: %d\n", *(_QWORD *)((char *)ptr + v0 + 8));
printf(" path: %s\n", *(const char **)((char *)ptr + v0 + 16));
printf(" size: %d\n", *(_QWORD *)((char *)ptr + v0 + 40));
}
++v1;
v0 += 80LL;
}
while ( *((_DWORD *)&ptr + 2) > (signed int)v1 );
return 0LL;
}

original_code:
int builtin_dumpfds(int argc, char **argv, int in, int out, int err){
  int i;
  for ( i = 0; i < fs.ft_length; i++){
    if ( ! fs.ftable[i].used )
      continue;
    printf("FD: %d\n", i);
    printf("  references: %d\n", (int)fs.ftable[i].references);
    printf("  offset:     %d\n", (int)fs.ftable[i].offset);
    printf("  path:       %s\n", fs.ftable[i].path);
    printf("  size:       %d\n", (int)fs.ftable[i].size);
  }
  return 0;
}

variable_types: argc int

variable_types:
argv
char **

variable_types: in int

variable_types: out int

variable_types: err int


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

result = 0LL;
memset(&history, 0, 0xA8uLL);
start = 0;
end = 0;
return result;
}

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

result = 0LL;
memset(&history, 0, 0xA8uLL);
start = 0;
end = 0;
return result;
}

original_code:
void rsh_history_init(){
  memset(history, 0, sizeof(char *) * (20 +1));
  start = 0;
  end = 0;
}

return_type: void


decompiled_code:
int rsh_term_init()
{
struct termios v1; // [rsp+0h] [rbp-48h] BYREF

tcgetattr(rsh_fd, &v1);
v1.c_cc[6] = 1;
v1.c_cc[5] = 0;
v1.c_lflag &= 0xFFFFFFF5;
return tcsetattr(rsh_fd, 0, &v1);
}

canonical_decompiled_code:
int func1()
{
struct termios v1; // [rsp+0h] [rbp-48h] BYREF

tcgetattr(rsh_fd, &v1);
v1.c_cc[6] = 1;
v1.c_cc[5] = 0;
v1.c_lflag &= 0xFFFFFFF5;
return tcsetattr(rsh_fd, 0, &v1);
}

original_code:
void rsh_term_init(){
  struct termios settings;
  tcgetattr(rsh_fd, &settings);
  settings.c_cc[6] = 1;
  settings.c_cc[5] = 0;
  settings.c_lflag &= ~0000010;
  settings.c_lflag &= ~0000002;
  tcsetattr(rsh_fd, 0, &settings);
}

variable_types: struct termios { unsigned int c_iflag; unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; }


decompiled_code:
void __fastcall rsh_set_input(int a1)
{
rsh_fd = a1;
}

canonical_decompiled_code:
void __fastcall func2(int a1)
{
rsh_fd = a1;
}

original_code:
void rsh_set_input(int fd){
  rsh_fd = fd;
}

variable_types: fd int


decompiled_code:
__int64 __fastcall rsh_history_add(char *s)
{
void *v2; // rdi
int v3; // ebx
int v4; // ebx
__int64 result; // rax

v2 = (void *)history[end];
if ( v2 )
free(v2);
v3 = end;
history[v3] = (__int64)strdup(s);
v4 = v3 + 1;
if ( v4 > 20 )
v4 = 0;
end = v4;
result = (unsigned int)start;
if ( v4 == start )
{
result = (unsigned int)(start + 1);
if ( (int)result > 20 )
result = 0LL;
start = result;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(char *s)
{
void *v2; // rdi
int v3; // ebx
int v4; // ebx
__int64 result; // rax

v2 = (void *)history[end];
if ( v2 )
free(v2);
v3 = end;
history[v3] = (__int64)strdup(s);
v4 = v3 + 1;
if ( v4 > 20 )
v4 = 0;
end = v4;
result = (unsigned int)start;
if ( v4 == start )
{
result = (unsigned int)(start + 1);
if ( (int)result > 20 )
result = 0LL;
start = result;
}
return result;
}

original_code:
void rsh_history_add(char *line){
  if ( history[end] )
    free(history[end]);
  history[end] = strdup(line);
  do { end++; if (end >= (20 +1)) end = 0; } while (0);
  if ( end == start )
    do { start++; if (start >= (20 +1)) start = 0; } while (0);
}

variable_types:
line
char *


decompiled_code:
void __fastcall rsh_historify(const char *a1)
{
char *v1; // rax
char *v2; // rbx

if ( *a1 )
{
v1 = strdup(a1);
v2 = v1;
if ( v1 )
{
v1[(int)(strlen(v1) - 1)] = 0;
if ( *v2 )
rsh_history_add(v2);
free(v2);
}
}
}

canonical_decompiled_code:
void __fastcall func5(const char *a1)
{
char *v1; // rax
char *v2; // rbx

if ( *a1 )
{
v1 = strdup(a1);
v2 = v1;
if ( v1 )
{
v1[(int)(strlen(v1) - 1)] = 0;
if ( *v2 )
func4(v2);
free(v2);
}
}
}

original_code:
void rsh_historify(char *line){
  int ok = 0;
  char *copy;
  int del;
  if ( strlen(line) < 1 )
    return;
  while ( *line ){
    if ( *line != ' ' || *line != '\t' || *line != '\n' ){
      ok = 1;
      break;
    }
  }
  if ( ! ok )
    return;
  copy = strdup(line);
  if ( ! copy )
    return;
  del = strlen(copy) - 1;
  copy[del] = 0;
  if ( strlen(copy) > 0 )
    rsh_history_add(copy);
  free(copy);
}

variable_types: ok int

variable_types:
copy
char *

variable_types: del int


decompiled_code:
int rsh_history_print()
{
int v0; // ebx
unsigned int v1; // ebp
__int64 v2; // rsi
int result; // eax

v0 = start;
if ( start != end )
{
v1 = 1;
do
{
v2 = v1++;
result = printf("%-3d %s\n", v2, (const char *)history[v0++]);
if ( v0 >= 21 )
v0 = 0;
}
while ( end != v0 );
}
return result;
}

canonical_decompiled_code:
int func6()
{
int v0; // ebx
unsigned int v1; // ebp
__int64 v2; // rsi
int result; // eax

v0 = start;
if ( start != end )
{
v1 = 1;
do
{
v2 = v1++;
result = printf("%-3d %s\n", v2, (const char *)history[v0++]);
if ( v0 >= 21 )
v0 = 0;
}
while ( end != v0 );
}
return result;
}

original_code:
void rsh_history_print(){
  int offset = start;
  int printed = 1;
  while ( offset != end ){
    printf("%-3d %s\n", printed++, history[offset]);
    do { offset++; if (offset >= (20 +1)) offset = 0; } while (0);
  }
}

variable_types: offset int

variable_types: printed int


original_code:
int rsh_buf_insert(struct rsh_buff *buf, char c){
  char d, *tmp;
  int offset;
  if ( ! buf->buf ){
    buf->buf = (char *)malloc(sizeof(char) * 128);
    if ( ! buf->buf )
      return -1;
    buf->size = 128;
    buf->offset = 0;
    buf->len = 0;
  }
  if ( buf->len >= buf->size ){
    tmp = (char *)malloc(buf->size + 128);
    if ( ! tmp ){
      return -1;
    }
    free(buf->buf);
    buf->size += 128;
    buf->buf = tmp;
  }
  offset = buf->offset++;
  while ( offset <= buf->len ){
    d = buf->buf[offset];
    buf->buf[offset++] = c;
    c = d;
  }
  buf->len++;
  buf->used = 1;
  return 0;
}

canonical_original_code:
int rsh_buf_insert(struct rsh_buff *buf, char c){
  char d; char *tmp;
  int offset;
  if ( ! buf->buf ){
    buf->buf = (char *)malloc(sizeof(char) * 128);
    if ( ! buf->buf )
      return -1;
    buf->size = 128;
    buf->offset = 0;
    buf->len = 0;
  }
  if ( buf->len >= buf->size ){
    tmp = (char *)malloc(buf->size + 128);
    if ( ! tmp ){
      return -1;
    }
    free(buf->buf);
    buf->size += 128;
    buf->buf = tmp;
  }
  offset = buf->offset++;
  while ( offset <= buf->len ){
    d = buf->buf[offset];
    buf->buf[offset++] = c;
    c = d;
  }
  buf->len++;
  buf->used = 1;
  return 0;
}

variable_types: struct rsh_buff { char *buf; int offset; int len; int size; int used; } *

variable_types: c char

variable_types: d char

variable_types:
tmp
char *


decompiled_code:
__int64 __fastcall rsh_buf_shift(__int64 a1, int a2)
{
__int64 result; // rax

if ( a2 )
{
result = *(unsigned int *)(a1 + 8);
if ( (int)result > 0 )
{
result = (unsigned int)(result - 1);
*(_DWORD *)(a1 + 8) = result;
}
}
else
{
result = *(unsigned int *)(a1 + 8);
if ( (int)result < *(_DWORD *)(a1 + 12) )
{
result = (unsigned int)(result + 1);
*(_DWORD *)(a1 + 8) = result;
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1, int a2)
{
__int64 result; // rax

if ( a2 )
{
result = *(unsigned int *)(a1 + 8);
if ( (int)result > 0 )
{
result = (unsigned int)(result - 1);
*(_DWORD *)(a1 + 8) = result;
}
}
else
{
result = *(unsigned int *)(a1 + 8);
if ( (int)result < *(_DWORD *)(a1 + 12) )
{
result = (unsigned int)(result + 1);
*(_DWORD *)(a1 + 8) = result;
}
}
return result;
}

original_code:
void rsh_buf_shift(struct rsh_buff *buf, int direction){
  if ( direction ){
    if ( buf->offset <= 0 )
      return;
    buf->offset--;
  } else {
    if ( buf->offset >= buf->len )
      return;
    buf->offset++;
  }
}

variable_types: direction int

user_defined_types: struct rsh_buff { char *buf; int offset; int len; int size; int used; }


original_code:
void rsh_buf_delete(struct rsh_buff *buf){
  int offset = buf->offset;
  if ( buf->offset == buf->len )
    return;
  while ( offset < buf->len ){
    buf->buf[offset] = buf->buf[offset+1];
    offset++;
  }
  if ( buf->len > 0 )
    buf->len--;
}


decompiled_code:
void __fastcall rsh_buf_backspace(__int64 a1)
{
rsh_buf_shift(a1, 1);
rsh_buf_delete(a1);
}

canonical_decompiled_code:
void __fastcall func10(__int64 a1)
{
func8(a1, 1);
func9(a1);
}

original_code:
void rsh_buf_backspace(struct rsh_buff *buf){
  rsh_buf_shift(buf, 1);
  rsh_buf_delete(buf);
}


decompiled_code:
__int64 __fastcall rsh_buf_copy(__int64 a1, __int64 a2)
{
int v3; // edi
int v4; // er12
void *v5; // rdi
__int64 result; // rax

v3 = *(_DWORD *)(a2 + 16);
*(_DWORD *)(a1 + 16) = v3;
v4 = *(_DWORD *)(a2 + 8);
*(_DWORD *)(a1 + 8) = v4;
*(_DWORD *)(a1 + 12) = *(_DWORD *)(a2 + 12);
*(_DWORD *)(a1 + 20) = *(_DWORD *)(a2 + 20);
if ( *(_QWORD *)a2 )
{
v5 = malloc(v3);
*(_QWORD *)a1 = v5;
if ( v5 )
{
memcpy(v5, *(const void **)a2, v4);
result = 0LL;
}
else
{
result = 0xFFFFFFFFLL;
}
}
else
{
*(_QWORD *)a1 = 0LL;
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func11(__int64 a1, __int64 a2)
{
int v3; // edi
int v4; // er12
void *v5; // rdi
__int64 result; // rax

v3 = *(_DWORD *)(a2 + 16);
*(_DWORD *)(a1 + 16) = v3;
v4 = *(_DWORD *)(a2 + 8);
*(_DWORD *)(a1 + 8) = v4;
*(_DWORD *)(a1 + 12) = *(_DWORD *)(a2 + 12);
*(_DWORD *)(a1 + 20) = *(_DWORD *)(a2 + 20);
if ( *(_QWORD *)a2 )
{
v5 = malloc(v3);
*(_QWORD *)a1 = v5;
if ( v5 )
{
memcpy(v5, *(const void **)a2, v4);
result = 0LL;
}
else
{
result = 0xFFFFFFFFLL;
}
}
else
{
*(_QWORD *)a1 = 0LL;
result = 0LL;
}
return result;
}

original_code:
int rsh_buf_copy(struct rsh_buff *dest, struct rsh_buff *src){
  dest->size = src->size;
  dest->offset = src->offset;
  dest->len = src->len;
  dest->used = src->used;
  if (src->buf){
    dest->buf = (char *)malloc(dest->size * sizeof(char));
    if ( ! dest->buf )
      return -1;
    memcpy(dest->buf, src->buf, dest->offset);
  } else {
    dest->buf = ((void *)0);
  }
  return 0;
}

variable_types:
src
struct rsh_buff *


original_code:
void rsh_buf_clean(struct rsh_buff *buf){
  if ( buf->buf ){
    free(buf->buf);
  }
  buf->buf = ((void *)0);
  buf->size = 0;
  buf->offset = 0;
  buf->used = 0;
  buf->len = 0;
}


decompiled_code:
__int64 __fastcall rsh_buf_append(__int64 a1, char a2)
{
int v2; // ebp
__int64 result; // rax

v2 = *(_DWORD *)(a1 + 8);
*(_DWORD *)(a1 + 8) = *(_DWORD *)(a1 + 12);
result = rsh_buf_insert(a1, a2);
*(_DWORD *)(a1 + 8) = v2;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func13(__int64 a1, char a2)
{
int v2; // ebp
__int64 result; // rax

v2 = *(_DWORD *)(a1 + 8);
*(_DWORD *)(a1 + 8) = *(_DWORD *)(a1 + 12);
result = func7(a1, a2);
*(_DWORD *)(a1 + 8) = v2;
return result;
}

original_code:
int rsh_buf_append(struct rsh_buff *buf, char c){
  int offset, ret;
  offset = buf->offset;
  buf->offset = buf->len;
  ret = rsh_buf_insert(buf, c);
  buf->offset = offset;
  return ret;
}

canonical_original_code:
int rsh_buf_append(struct rsh_buff *buf, char c){
  int offset; int ret;
  offset = buf->offset;
  buf->offset = buf->len;
  ret = rsh_buf_insert(buf, c);
  buf->offset = offset;
  return ret;
}

variable_types: ret int


decompiled_code:
int __fastcall rsh_buf_display(__int64 a1)
{
__int64 v1; // rbx

printf("\x1B[u");
printf("\x1B[K");
if ( *(int *)(a1 + 12) > 0 )
{
v1 = 0LL;
do
putchar(*(char *)(*(_QWORD *)a1 + v1++));
while ( *(_DWORD *)(a1 + 12) > (int)v1 );
}
printf("\x1B[u");
printf("\x1B[%dD", 1LL);
printf("\x1B[%dC", (unsigned int)(*(_DWORD *)(a1 + 8) + 1));
return fflush(stdout);
}

canonical_decompiled_code:
int __fastcall func14(__int64 a1)
{
__int64 v1; // rbx

printf("\x1B[u");
printf("\x1B[K");
if ( *(int *)(a1 + 12) > 0 )
{
v1 = 0LL;
do
putchar(*(char *)(*(_QWORD *)a1 + v1++));
while ( *(_DWORD *)(a1 + 12) > (int)v1 );
}
printf("\x1B[u");
printf("\x1B[%dD", 1LL);
printf("\x1B[%dC", (unsigned int)(*(_DWORD *)(a1 + 8) + 1));
return fflush(stdout);
}

original_code:
void rsh_buf_display(struct rsh_buff *buf){
  int i = 0;
  printf("\033[u");
  printf("\033[K");
  while ( i < buf->len )
    putchar(buf->buf[i++]);
  printf("\033[u");
  printf("\033[%dD", 1);;
  printf("\033[%dC", buf->offset + 1);;
  fflush(stdout);
}

variable_types: i int


decompiled_code:
__int64 __fastcall rsh_stack_push(_QWORD *a1, int a2)
{
_QWORD *v2; // rax

v2 = malloc(0x10uLL);
if ( !v2 )
return 0xFFFFFFFFLL;
*(_DWORD *)v2 = a2;
v2[1] = *a1;
*a1 = v2;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func20(_QWORD *a1, int a2)
{
_QWORD *v2; // rax

v2 = malloc(0x10uLL);
if ( !v2 )
return 0xFFFFFFFFLL;
*(_DWORD *)v2 = a2;
v2[1] = *a1;
*a1 = v2;
return 0LL;
}

original_code:
int rsh_stack_push(struct rsh_history_stack *stack, int text){
  struct rsh_history_frame *frame =
    (struct rsh_history_frame *)malloc(sizeof(struct rsh_history_frame));
  if ( ! frame )
    return -1;
  frame->text = text;
  frame->next = stack->top;
  stack->top = frame;
  return 0;
}

variable_types: struct rsh_history_stack { struct rsh_history_frame { int text; struct rsh_history_frame *next; } *top; } *

variable_types: text int

user_defined_types: struct rsh_history_stack { struct rsh_history_frame *top; }


decompiled_code:
__int64 __fastcall rsh_stack_pop(void **a1)
{
void *v1; // rax
unsigned int v2; // ebx

v1 = *a1;
if ( !*a1 )
return (unsigned int)-1;
v2 = *(_DWORD *)v1;
*a1 = (void *)*((_QWORD *)v1 + 1);
free(v1);
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func21(void **a1)
{
void *v1; // rax
unsigned int v2; // ebx

v1 = *a1;
if ( !*a1 )
return (unsigned int)-1;
v2 = *(_DWORD *)v1;
*a1 = (void *)*((_QWORD *)v1 + 1);
free(v1);
return v2;
}

original_code:
int rsh_stack_pop(struct rsh_history_stack *stack){
  int frame_data;
  struct rsh_history_frame *frame;
  if ( ! stack->top )
    return -1;
  frame = stack->top;
  frame_data = stack->top->text;
  (stack->top = stack->top->next);
  free(frame);
  return frame_data;
}

variable_types: struct rsh_history_frame { int text; struct rsh_history_frame *next; } *


decompiled_code:
__int64 __fastcall rsh_readbuf(_BYTE *a1, unsigned __int64 a2)
{
__int64 result; // rax

if ( interactive )
result = rsh_read_term(a1, a2);
else
result = rsh_read_file(a1, a2);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func27(_BYTE *a1, unsigned __int64 a2)
{
__int64 result; // rax

if ( interactive )
result = func26(a1, a2);
else
result = func3(a1, a2);
return result;
}

original_code:
size_t rsh_readbuf(char *buffer, size_t max){
  if ( interactive )
    return _rsh_read_term(buffer, max);
  else
    return _rsh_read_file(buffer, max);
}

canonical_original_code:
unsigned long rsh_readbuf(char *buffer, unsigned long max){
  if ( interactive )
    return _rsh_read_term(buffer, max);
  else
    return _rsh_read_file(buffer, max);
}

variable_types:
buffer
char *

variable_types:
max
unsigned long

return_type: unsigned long


decompiled_code:
int rsh_history_display_async()
{
putchar(10);
rsh_history_print();
prompt_print();
printf("\x1B[s");
return rsh_buf_display((__int64)&buf);
}

canonical_decompiled_code:
int func28()
{
putchar(10);
func6();
prompt_print();
printf("\x1B[s");
return func14((__int64)&buf);
}

original_code:
void rsh_history_display_async(int sig){
  printf("\n");
  rsh_history_print();
  prompt_print();
  printf("\033[s");
  rsh_buf_display(&buf);
}

variable_types: sig int


decompiled_code:
int rsh_reset_input()
{
prompt_print();
printf("\x1B[s");
return rsh_buf_display((__int64)&buf);
}

canonical_decompiled_code:
int func29()
{
prompt_print();
printf("\x1B[s");
return func14((__int64)&buf);
}

original_code:
void rsh_reset_input(){
  prompt_print();
  printf("\033[s");
  rsh_buf_display(&buf);
}


decompiled_code:
char *__fastcall stringify_token(int a1)
{
return (&lexxer_tokens)[a1];
}

canonical_decompiled_code:
char *__fastcall func0(int a1)
{
return (&lexxer_tokens)[a1];
}

original_code:
inline const char *stringify_token(int type){
  return lexxer_tokens[type];
}

canonical_original_code:
inline char *stringify_token(int type){
  return lexxer_tokens[type];
}

variable_types: type int

return_type: char *


decompiled_code:
__int64 __fastcall token_seqlen(__int64 a1)
{
__int64 result; // rax
__int64 v2; // rdi

result = *(unsigned int *)(a1 + 8);
if ( (_DWORD)result )
{
v2 = a1 + 24;
LODWORD(result) = 0;
do
{
result = (unsigned int)(result + 1);
v2 += 16LL;
}
while ( *(_DWORD *)(v2 - 16) );
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1)
{
__int64 result; // rax
__int64 v2; // rdi

result = *(unsigned int *)(a1 + 8);
if ( (_DWORD)result )
{
v2 = a1 + 24;
LODWORD(result) = 0;
do
{
result = (unsigned int)(result + 1);
v2 += 16LL;
}
while ( *(_DWORD *)(v2 - 16) );
}
return result;
}

original_code:
int token_seqlen(struct rsh_token *tokens){
  int len = 0;
  while ( tokens[len].type != 0 )
    len++;
  return len;
}

variable_types: struct rsh_token { char *tok; int type; } *

variable_types: len int


decompiled_code:
char *__fastcall token_add(__int64 *a1, int *a2, __int64 a3)
{
void *v4; // r14
int v5; // ebx
__int64 v6; // rbx
char *result; // rax
const char *v8; // rdi
_QWORD *v9; // rax
void *v10; // r15

if ( !*a1 )
{
*a1 = (__int64)malloc(0x80uLL);
*a2 = 8;
v9 = (_QWORD *)*a1;
*v9 = 0LL;
v9[15] = 0LL;
memset(
(void *)((unsigned __int64)(v9 + 1) & 0xFFFFFFFFFFFFFFF8LL),
0,
8LL * (((unsigned int)v9 - (((_DWORD)v9 + 8) & 0xFFFFFFF8) + 128) >> 3));
}
v4 = (void *)*a1;
v5 = token_seqlen(*a1);
if ( v5 + 1 >= *a2 )
{
v10 = malloc(16LL * (*a2 + 8));
memcpy(v10, v4, 16LL * *a2);
free(v4);
*a2 += 8;
*a1 = (__int64)v10;
}
v6 = *a1 + 16LL * v5;
result = (char *)*(unsigned int *)(a3 + 8);
*(_DWORD *)(v6 + 8) = (_DWORD)result;
v8 = *(const char **)a3;
if ( *(_QWORD *)a3 )
{
result = strdup(v8);
v8 = result;
}
*(_QWORD *)v6 = v8;
*(_DWORD *)(v6 + 24) = 0;
*(_QWORD *)(v6 + 16) = 0LL;
return result;
}

canonical_decompiled_code:
char *__fastcall func2(__int64 *a1, int *a2, __int64 a3)
{
void *v4; // r14
int v5; // ebx
__int64 v6; // rbx
char *result; // rax
const char *v8; // rdi
_QWORD *v9; // rax
void *v10; // r15

if ( !*a1 )
{
*a1 = (__int64)malloc(0x80uLL);
*a2 = 8;
v9 = (_QWORD *)*a1;
*v9 = 0LL;
v9[15] = 0LL;
memset(
(void *)((unsigned __int64)(v9 + 1) & 0xFFFFFFFFFFFFFFF8LL),
0,
8LL * (((unsigned int)v9 - (((_DWORD)v9 + 8) & 0xFFFFFFF8) + 128) >> 3));
}
v4 = (void *)*a1;
v5 = func1(*a1);
if ( v5 + 1 >= *a2 )
{
v10 = malloc(16LL * (*a2 + 8));
memcpy(v10, v4, 16LL * *a2);
free(v4);
*a2 += 8;
*a1 = (__int64)v10;
}
v6 = *a1 + 16LL * v5;
result = (char *)*(unsigned int *)(a3 + 8);
*(_DWORD *)(v6 + 8) = (_DWORD)result;
v8 = *(const char **)a3;
if ( *(_QWORD *)a3 )
{
result = strdup(v8);
v8 = result;
}
*(_QWORD *)v6 = v8;
*(_DWORD *)(v6 + 24) = 0;
*(_QWORD *)(v6 + 16) = 0LL;
return result;
}

original_code:
void token_add(struct rsh_token **storage, int *size, struct rsh_token *tok){
  struct rsh_token *tmp;
  struct rsh_token *storage_elems;
  int offset;
  if ( ! (*storage) ){
    (*storage) = (struct rsh_token *)malloc(8 * sizeof(struct rsh_token));
    *size = 8;
    memset(*storage, 0, 8 * sizeof(struct rsh_token));
  }
  offset = token_seqlen(*storage);
  if ( (offset + 1) >= *size){
    tmp = malloc(sizeof(struct rsh_token) * ((*size) + 8));
    memcpy(tmp, *storage, (*size) * sizeof(struct rsh_token));
    free(*storage);
    *size += 8;
    *storage = tmp;
  }
  storage_elems = *storage;
  storage_elems += offset;
  storage_elems->type = tok->type;
  storage_elems->tok = tok->tok ? strdup(tok->tok) : ((void *)0);
  storage_elems++;
  storage_elems->type = 0;
  storage_elems->tok = ((void *)0);
}

variable_types: struct rsh_token { char *tok; int type; } **

variable_types:
size
int *

variable_types:
tok
struct rsh_token *

variable_types: offset int


decompiled_code:
__int64 read_next_statement()
{
__int64 result; // rax
int v1; // eax
__int64 v2; // [rsp+0h] [rbp-28h] BYREF
int v3; // [rsp+8h] [rbp-20h]
int v4; // [rsp+14h] [rbp-14h] BYREF
__int64 v5[2]; // [rsp+18h] [rbp-10h] BYREF

v5[0] = 0LL;
v4 = 0;
result = 0LL;
if ( !EOF_encountered )
{
cur_token = 0LL;
token_add(v5, &v4, (__int64)&null_tok);
while ( 1 )
{
cur_token = 0LL;
v1 = yylex();
if ( v1 == 4 )
break;
if ( v1 == 20 )
{
EOF_encountered = 1;
break;
}
v2 = cur_token;
v3 = v1;
token_add(v5, &v4, (__int64)&v2);
}
result = v5[0];
}
return result;
}

canonical_decompiled_code:
__int64 func3()
{
__int64 result; // rax
int v1; // eax
__int64 v2; // [rsp+0h] [rbp-28h] BYREF
int v3; // [rsp+8h] [rbp-20h]
int v4; // [rsp+14h] [rbp-14h] BYREF
__int64 v5[2]; // [rsp+18h] [rbp-10h] BYREF

v5[0] = 0LL;
v4 = 0;
result = 0LL;
if ( !EOF_encountered )
{
cur_token = 0LL;
func2(v5, &v4, (__int64)&null_tok);
while ( 1 )
{
cur_token = 0LL;
v1 = yylex();
if ( v1 == 4 )
break;
if ( v1 == 20 )
{
EOF_encountered = 1;
break;
}
v2 = cur_token;
v3 = v1;
func2(v5, &v4, (__int64)&v2);
}
result = v5[0];
}
return result;
}

original_code:
struct rsh_token *read_next_statement(){
  struct rsh_token *tokens = ((void *)0);
  int toktype;
  int size = 0;
  if ( EOF_encountered ){
    return ((void *)0);
  }
  cur_token = ((void *)0);
  token_add(&tokens, &size, &null_tok);
  while ( 1 ){
    cur_token = ((void *)0);
    toktype = yylex();
    if ( toktype == 4 )
      break;
    if ( toktype == 20 ){
      EOF_encountered = 1;
      break;
    }
    struct rsh_token tok = { cur_token, toktype };
    token_add(&tokens, &size, &tok);
  }
  return tokens;
}

variable_types: toktype int

variable_types: size int

return_type: struct rsh_token { char *tok; int type; } *


decompiled_code:
char *__fastcall string_join(char *s, char *a2)
{
char *v2; // r12
int v3; // er13
int v4; // er13
size_t v5; // rax
size_t v6; // r14
size_t v7; // rax

if ( s && !a2 )
return strdup(s);
if ( !s && a2 )
return strdup(a2);
v3 = strlen(s);
v4 = strlen(a2) + v3;
v2 = (char *)malloc(v4 + 1);
v5 = strlen(s);
memcpy(v2, s, v5);
v6 = strlen(a2);
v7 = strlen(s);
memcpy(&v2[v7], a2, v6);
v2[v4] = 0;
return v2;
}

canonical_decompiled_code:
char *__fastcall func4(char *s, char *a2)
{
char *v2; // r12
int v3; // er13
int v4; // er13
size_t v5; // rax
size_t v6; // r14
size_t v7; // rax

if ( s && !a2 )
return strdup(s);
if ( !s && a2 )
return strdup(a2);
v3 = strlen(s);
v4 = strlen(a2) + v3;
v2 = (char *)malloc(v4 + 1);
v5 = strlen(s);
memcpy(v2, s, v5);
v6 = strlen(a2);
v7 = strlen(s);
memcpy(&v2[v7], a2, v6);
v2[v4] = 0;
return v2;
}

original_code:
char *string_join(char *s1, char *s2){
  char *new_str;
  int new_len;
  if ( s1 && ! s2 ){
    return strdup(s1);
  }
  if ( ! s1 && s2 ){
    return strdup(s2);
  }
  new_len = strlen(s1) + strlen(s2);
  new_str = (char *)malloc(new_len + 1);
  memcpy(new_str, s1, strlen(s1));
  memcpy(new_str+strlen(s1), s2, strlen(s2));
  new_str[new_len] = 0;
  return new_str;
}


preparse

decompiled_code:
__int64 __fastcall preparse(__int64 a1)
{
int v1; // er12
__int64 v2; // rbx
__int64 v3; // r13
int v4; // ebp
int v5; // er14
int v6; // er12
__int64 v7; // rbp
int v8; // er15
char *v10; // [rsp+0h] [rbp-98h] BYREF
int v11; // [rsp+8h] [rbp-90h]
int v12; // [rsp+1Ch] [rbp-7Ch] BYREF
char *v13; // [rsp+20h] [rbp-78h] BYREF
__int64 v14; // [rsp+28h] [rbp-70h] BYREF
__int64 v15; // [rsp+30h] [rbp-68h] BYREF
__int64 v16; // [rsp+38h] [rbp-60h] BYREF
char *v17; // [rsp+40h] [rbp-58h] BYREF
int v18; // [rsp+48h] [rbp-50h]
char *v19; // [rsp+50h] [rbp-48h] BYREF
int v20; // [rsp+58h] [rbp-40h]

v16 = 0LL;
v1 = token_seqlen(a1);
v12 = 0;
token_add(&v16, &v12, (__int64)&null_tok);
if ( v1 > 0 )
{
v2 = a1;
v3 = a1 + 16LL * (unsigned int)(v1 - 1) + 16;
v4 = 0;
v5 = 0;
v6 = 0;
while ( 2 )
{
switch ( *(_DWORD *)(v2 + 8) )
{
case 1:
if ( v4 == 1 )
goto LABEL_56;
goto LABEL_55;
case 2:
if ( (unsigned int)(v6 - 1) <= 1 || v6 == 6 )
goto LABEL_56;
token_add(&v16, &v12, v2);
v6 = 6;
goto LABEL_11;
case 3:
v19 = 0LL;
v20 = 0;
symbol_to_word_tok(v2, (__int64)&v19);
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 5:
v5 = v5 == 0 ? 3 : 0;
goto LABEL_11;
case 6:
if ( v6 == 2 )
{
v10 = (char *)asc_C30;
v11 = 1;
append_to_tokseq(v16, &v12, &v10);
}
else
{
v6 = v6 != 1;
}
goto LABEL_11;
case 7:
if ( v6 == 1 )
{
v10 = (char *)&asc_C30[1];
v11 = 1;
append_to_tokseq(v16, &v12, &v10);
}
else
{
v6 = 2 * (v6 != 2);
}
goto LABEL_11;
case 8:
v20 = 1;
v19 = (char *)&asc_C30[2];
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 9:
v20 = 1;
v19 = (char *)&asc_C30[3];
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0xA:
v20 = 1;
v19 = (char *)&asc_C30[4];
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0xB:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = (char *)&asc_C30[5];
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0xC:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = (char *)&asc_C30[6];
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0xD:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = "2>";
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0xE:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = ">>";
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0xF:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = "2>>";
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0x10:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = "|";
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0x11:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
v20 = 1;
v19 = "2|";
append_to_tokseq(v16, &v12, &v19);
goto LABEL_11;
case 0x12:
if ( (unsigned int)(v6 - 1) > 1 )
goto LABEL_55;
LABEL_56:
append_to_tokseq(v16, &v12, (char **)v2);
goto LABEL_11;
case 0x13:
if ( (unsigned int)(v6 - 1) <= 1 )
goto LABEL_11;
return v16;
case 0x15:
if ( (unsigned int)(v6 - 1) > 1 )
{
LABEL_55:
token_add(&v16, &v12, v2);
}
else
{
v20 = 1;
v19 = "&";
append_to_tokseq(v16, &v12, &v19);
}
goto LABEL_11;
case 0x17:
if ( v6 == 1 )
{
v19 = "$*";
v20 = 1;
append_to_tokseq(v16, &v12, &v19);
}
else
{
v15 = 0LL;
v14 = 0LL;
v13 = 0LL;
symtable_numeric(&v15, &v14, &v13);
v19 = " ";
v20 = 18;
v8 = 1;
while ( (unsigned int)symtable_numeric(&v15, &v14, &v13) )
{
v18 = 1;
v17 = v13;
if ( v4 == 1 )
{
if ( !v8 )
append_to_tokseq(v16, &v12, &v19);
append_to_tokseq(v16, &v12, &v17);
}
else
{
if ( !v8 )
token_add(&v16, &v12, (__int64)&v19);
token_add(&v16, &v12, (__int64)&v17);
}
v8 = 0;
}
}
goto LABEL_11;
default:
LABEL_11:
v7 = v16;
v4 = *(_DWORD *)(v7 + 16LL * (int)token_seqlen(v16) - 8);
v2 += 16LL;
if ( v2 != v3 )
continue;
return v16;
}
}
}
return v16;
}

original_code:
struct rsh_token *preparse(struct rsh_token *tokens){
  struct rsh_token prev_tok = {((void *)0), 0};
  struct rsh_token tmp;
  struct rsh_token numeric_var;
  struct rsh_token *new_seq = ((void *)0);
  struct sym_entry *status;
  char *name, *data;
  int seq_len = token_seqlen(tokens);
  int tokind = 0;
  int size = 0;
  int state = 0;
  int backticks = 0;
  int start;
  token_add(&new_seq, &size, &null_tok);
  while ( tokind < seq_len){
    switch (tokens[tokind].type){
    case 1:
      if ( prev_tok.type == 1 ){
 _append_to_tokseq(new_seq, &size, &(tokens[tokind]));
      } else {
 token_add(&new_seq, &size, &(tokens[tokind]));
      }
      break;
    case 2:
      if ( state == 1 || state == 2 || state == 6){
 _append_to_tokseq(new_seq, &size, &(tokens[tokind]));
 break;
      }
      token_add(&new_seq, &size, &(tokens[tokind]));
      state = 6;
      break;
    case 3:
      tmp.tok = ((void *)0);
      tmp.type = 0;
      _symbol_to_word_tok(&(tokens[tokind]), &tmp);
      _append_to_tokseq(new_seq, &size, &tmp);
      break;
    case 5:
      if ( backticks )
 backticks = 0;
      else
 backticks = 3;
      break;
    case 6:
      if ( state == 2 ){
 struct rsh_token tmp = {"'", 1};
 _append_to_tokseq(new_seq, &size, &tmp);
      } else if ( state == 1 ) {
 state = 0;
      } else {
 state = 1;
      }
      break;
    case 7:
      if ( state == 1 ){
 struct rsh_token tmp = {"\"", 1};
 _append_to_tokseq(new_seq, &size, &tmp);
      } else if ( state == 2 ) {
 state = 0;
      } else {
 state = 2;
      }
      break;
    case 8:
      if ( state != 1 && state != 2 ){
 tmp.type = 1;
 tmp.tok = "{";
 _append_to_tokseq(new_seq, &size, &tmp);
      } else {
 tmp.type = 1;
 tmp.tok = "{";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 9:
      if ( state != 1 && state != 2 ){
 tmp.type = 1;
 tmp.tok = "}";
 _append_to_tokseq(new_seq, &size, &tmp);
      } else {
 tmp.type = 1;
 tmp.tok = "}";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 10:
      if ( state != 1 && state != 2 ){
 tmp.type = 1;
 tmp.tok = "*";
 _append_to_tokseq(new_seq, &size, &tmp);
      } else {
 tmp.type = 1;
 tmp.tok = "*";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 11:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "<";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 12:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = ">";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 13:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "2>";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 14:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = ">>";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 15:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "2>>";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 16:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "|";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 17:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "2|";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 21:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "&";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 23:
      if ( state == 1 ){
 tmp.tok = "$*";
 tmp.type = 1;
 _append_to_tokseq(new_seq, &size, &tmp);
 break;
      }
      status = ((void *)0);
      name = ((void *)0);
      data = ((void *)0);
      symtable_numeric(&status, &name, &data);
      tmp.tok = " ";
      tmp.type = 18;
      start = 1;
      while ( symtable_numeric(&status, &name, &data) ){
 numeric_var.type = 1;
 numeric_var.tok = data;
 if ( prev_tok.type == 1 ){
   if ( ! start )
     _append_to_tokseq(new_seq, &size, &tmp);
   else
     start = 0;
   _append_to_tokseq(new_seq, &size, &numeric_var);
 } else {
   if ( ! start )
     token_add(&new_seq, &size, &tmp);
   else
     start = 0;
   token_add(&new_seq, &size, &numeric_var);
 }
      }
      break;
    case 18:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 _append_to_tokseq(new_seq, &size, &(tokens[tokind]));
      }
      break;
    case 19:
      if ( state != 1 && state != 2 )
 return new_seq;
      break;
    default:
      break;
    }
    prev_tok.type = new_seq[token_seqlen(new_seq)-1].type;
    prev_tok.tok = new_seq[token_seqlen(new_seq)-1].tok;
    tokind++;
  }
  return new_seq;
}

canonical_original_code:
struct rsh_token *preparse(struct rsh_token *tokens){
  struct rsh_token prev_tok = {((void *)0), 0};
  struct rsh_token tmp;
  struct rsh_token numeric_var;
  struct rsh_token *new_seq = ((void *)0);
  struct sym_entry *status;
  char *name; char *data;
  int seq_len = token_seqlen(tokens);
  int tokind = 0;
  int size = 0;
  int state = 0;
  int backticks = 0;
  int start;
  token_add(&new_seq, &size, &null_tok);
  while ( tokind < seq_len){
    switch (tokens[tokind].type){
    case 1:
      if ( prev_tok.type == 1 ){
 _append_to_tokseq(new_seq, &size, &(tokens[tokind]));
      } else {
 token_add(&new_seq, &size, &(tokens[tokind]));
      }
      break;
    case 2:
      if ( state == 1 || state == 2 || state == 6){
 _append_to_tokseq(new_seq, &size, &(tokens[tokind]));
 break;
      }
      token_add(&new_seq, &size, &(tokens[tokind]));
      state = 6;
      break;
    case 3:
      tmp.tok = ((void *)0);
      tmp.type = 0;
      _symbol_to_word_tok(&(tokens[tokind]), &tmp);
      _append_to_tokseq(new_seq, &size, &tmp);
      break;
    case 5:
      if ( backticks )
 backticks = 0;
      else
 backticks = 3;
      break;
    case 6:
      if ( state == 2 ){
 struct rsh_token tmp = {"'", 1};
 _append_to_tokseq(new_seq, &size, &tmp);
      } else if ( state == 1 ) {
 state = 0;
      } else {
 state = 1;
      }
      break;
    case 7:
      if ( state == 1 ){
 struct rsh_token tmp = {"\"", 1};
 _append_to_tokseq(new_seq, &size, &tmp);
      } else if ( state == 2 ) {
 state = 0;
      } else {
 state = 2;
      }
      break;
    case 8:
      if ( state != 1 && state != 2 ){
 tmp.type = 1;
 tmp.tok = "{";
 _append_to_tokseq(new_seq, &size, &tmp);
      } else {
 tmp.type = 1;
 tmp.tok = "{";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 9:
      if ( state != 1 && state != 2 ){
 tmp.type = 1;
 tmp.tok = "}";
 _append_to_tokseq(new_seq, &size, &tmp);
      } else {
 tmp.type = 1;
 tmp.tok = "}";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 10:
      if ( state != 1 && state != 2 ){
 tmp.type = 1;
 tmp.tok = "*";
 _append_to_tokseq(new_seq, &size, &tmp);
      } else {
 tmp.type = 1;
 tmp.tok = "*";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 11:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "<";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 12:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = ">";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 13:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "2>";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 14:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = ">>";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 15:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "2>>";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 16:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "|";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 17:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "2|";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 21:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 tmp.type = 1;
 tmp.tok = "&";
 _append_to_tokseq(new_seq, &size, &tmp);
      }
      break;
    case 23:
      if ( state == 1 ){
 tmp.tok = "$*";
 tmp.type = 1;
 _append_to_tokseq(new_seq, &size, &tmp);
 break;
      }
      status = ((void *)0);
      name = ((void *)0);
      data = ((void *)0);
      symtable_numeric(&status, &name, &data);
      tmp.tok = " ";
      tmp.type = 18;
      start = 1;
      while ( symtable_numeric(&status, &name, &data) ){
 numeric_var.type = 1;
 numeric_var.tok = data;
 if ( prev_tok.type == 1 ){
   if ( ! start )
     _append_to_tokseq(new_seq, &size, &tmp);
   else
     start = 0;
   _append_to_tokseq(new_seq, &size, &numeric_var);
 } else {
   if ( ! start )
     token_add(&new_seq, &size, &tmp);
   else
     start = 0;
   token_add(&new_seq, &size, &numeric_var);
 }
      }
      break;
    case 18:
      if ( state != 1 && state != 2 ){
 token_add(&new_seq, &size, &(tokens[tokind]));
      } else {
 _append_to_tokseq(new_seq, &size, &(tokens[tokind]));
      }
      break;
    case 19:
      if ( state != 1 && state != 2 )
 return new_seq;
      break;
    default:
      break;
    }
    prev_tok.type = new_seq[token_seqlen(new_seq)-1].type;
    prev_tok.tok = new_seq[token_seqlen(new_seq)-1].tok;
    tokind++;
  }
  return new_seq;
}

variable_types:
tokens
struct rsh_token *

variable_types: struct rsh_token { char *tok; int type; }

variable_types: struct sym_entry { char *name; char *data; struct sym_entry *next; } *

variable_types:
name
char *

variable_types:
data
char *

variable_types: tokind int

variable_types: state int

variable_types: backticks int

variable_types: start int


decompiled_code:
__int64 __fastcall exec_token_seq(__int64 a1)
{
__int64 v1; // rbx
__int64 result; // rax

v1 = preparse(a1);
result = token_seqlen(v1);
if ( (_DWORD)result )
result = rsh_command(v1);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1)
{
__int64 v1; // rbx
__int64 result; // rax

v1 = func7(a1);
result = func1(v1);
if ( (_DWORD)result )
result = rsh_command(v1);
return result;
}

original_code:
int exec_token_seq(struct rsh_token *tokens){
  struct rsh_token *real_tokens;
  real_tokens = preparse(tokens);
  if ( ! token_seqlen(real_tokens) )
    return 0;
  return rsh_command(real_tokens);
}

variable_types: struct rsh_token { char *tok; int type; } *


decompiled_code:
__int64 __fastcall init_rsh_pgroup(int a1)
{
char *v1; // rbx
__int64 v2; // rax
__int64 v3; // rdx
int v4; // eax
__int64 v5; // rax

if ( a1 <= 0 )
return 0xFFFFFFFFLL;
qword_AC8 = 0LL;
qword_AD0 = 0LL;
qword_AD8 = 0LL;
rsh_pgroup = malloc(8LL * a1);
memset(rsh_pgroup, 0, 8LL * a1);
LODWORD(qword_AD8) = getpid();
HIDWORD(qword_AD8) = tcgetpgrp(0);
qword_AC8 = (unsigned int)a1;
qword_AD0 = 0x200000001LL;
v1 = (char *)malloc(0x108uLL);
*(_DWORD *)v1 = getpid();
*((_DWORD *)v1 + 1) = getpid();
if ( interactive )
setpgid(*(_DWORD *)v1, 0);
*((_DWORD *)v1 + 5) = 0;
*((_DWORD *)v1 + 6) = 1;
*((_DWORD *)v1 + 7) = 6845298;
*((_DWORD *)v1 + 2) = 0;
*((_DWORD *)v1 + 3) = 1;
*((_DWORD *)v1 + 4) = 2;
v2 = script;
*((_QWORD *)v1 + 30) = script;
v3 = script_argv;
*((_QWORD *)v1 + 31) = script_argv;
if ( v2 )
{
v4 = *((_DWORD *)v1 + 64);
if ( *(_QWORD *)(v3 + 8LL * v4) )
{
v5 = v4 + 1;
do
*((_DWORD *)v1 + 64) = v5++;
while ( *(_QWORD *)(v3 + 8 * v5 - 8) );
}
}
tcgetattr(0, (struct termios *)(v1 + 176));
*(_QWORD *)rsh_pgroup = v1;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1)
{
char *v1; // rbx
__int64 v2; // rax
__int64 v3; // rdx
int v4; // eax
__int64 v5; // rax

if ( a1 <= 0 )
return 0xFFFFFFFFLL;
qword_AC8 = 0LL;
qword_AD0 = 0LL;
qword_AD8 = 0LL;
rsh_pgroup = malloc(8LL * a1);
memset(rsh_pgroup, 0, 8LL * a1);
LODWORD(qword_AD8) = getpid();
HIDWORD(qword_AD8) = tcgetpgrp(0);
qword_AC8 = (unsigned int)a1;
qword_AD0 = 0x200000001LL;
v1 = (char *)malloc(0x108uLL);
*(_DWORD *)v1 = getpid();
*((_DWORD *)v1 + 1) = getpid();
if ( interactive )
setpgid(*(_DWORD *)v1, 0);
*((_DWORD *)v1 + 5) = 0;
*((_DWORD *)v1 + 6) = 1;
*((_DWORD *)v1 + 7) = 6845298;
*((_DWORD *)v1 + 2) = 0;
*((_DWORD *)v1 + 3) = 1;
*((_DWORD *)v1 + 4) = 2;
v2 = script;
*((_QWORD *)v1 + 30) = script;
v3 = script_argv;
*((_QWORD *)v1 + 31) = script_argv;
if ( v2 )
{
v4 = *((_DWORD *)v1 + 64);
if ( *(_QWORD *)(v3 + 8LL * v4) )
{
v5 = v4 + 1;
do
*((_DWORD *)v1 + 64) = v5++;
while ( *(_QWORD *)(v3 + 8 * v5 - 8) );
}
}
tcgetattr(0, (struct termios *)(v1 + 176));
*(_QWORD *)rsh_pgroup = v1;
return 0LL;
}

original_code:
int init_rsh_pgroup(int procs){
  if ( procs < 1 )
    return -1;
  memset(&rsh_pgroup, 0, sizeof(rsh_pgroup));
  rsh_pgroup.pgroup = (struct rsh_process **)
    malloc(sizeof(struct rsh_process *) * procs);
  memset(rsh_pgroup.pgroup, 0, sizeof(struct rsh_process *) * procs);
  if ( ! rsh_pgroup.pgroup )
    return -1;
  rsh_pgroup.pid = getpid();
  rsh_pgroup.pgid = tcgetpgrp(0);
  rsh_pgroup.max_procs = procs;
  rsh_pgroup.stdin = 0;
  rsh_pgroup.stdout = 1;
  rsh_pgroup.stderr = 2;
  struct rsh_process *self = (struct rsh_process *)
    malloc(sizeof(struct rsh_process));
  self->pid = getpid();
  self->pgid = getpid();
  if ( interactive )
    setpgid(self->pid, 0);
  self->background = 0;
  self->running = 1;
  memcpy(self->name, "rsh", 4);
  self->stdin = 0;
  self->stdout = 1;
  self->stderr = 2;
  self->command = script;
  self->argv = script_argv;
  if ( self->command )
    while ( self->argv[self->argc] != ((void *)0) )
      self->argc++;
  tcgetattr(0, &self->term);
  rsh_pgroup.pgroup[0] = self;
  return 0;
}

variable_types: procs int

variable_types: struct rsh_process { int pid; unsigned int pgid; int stdin; int stdout; int stderr; int background; int running; char name[128]; int pipe[2]; int pipe_used; int pipe_lane; int display_exit; struct termios { unsigned int c_iflag; unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; } term; char *command; char **argv; int argc; } *

user_defined_types: struct rsh_process { int pid; unsigned int pgid; int stdin; int stdout; int stderr; int background; int running; char name[128]; int pipe[2]; int pipe_used; int pipe_lane; int display_exit; struct termios term; char *command; char **argv; int argc; }


decompiled_code:
int save_default_term_settings()
{
return tcgetattr(0, &defaults);
}

canonical_decompiled_code:
int func1()
{
return tcgetattr(0, &defaults);
}

original_code:
void save_default_term_settings(){
  tcgetattr(0, &defaults);
}


decompiled_code:
__int64 __fastcall rsh_register_pipe(__int64 a1)
{
__int64 result; // rax

rsh_pipe = *(_DWORD *)a1;
result = *(unsigned int *)(a1 + 4);
*(&rsh_pipe + 1) = result;
pipe_used = 1;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1)
{
__int64 result; // rax

rsh_pipe = *(_DWORD *)a1;
result = *(unsigned int *)(a1 + 4);
*(&rsh_pipe + 1) = result;
pipe_used = 1;
return result;
}

original_code:
void rsh_register_pipe(int pip[2]){
  rsh_pipe[0] = pip[0];
  rsh_pipe[1] = pip[1];
  pipe_used = 1;
}

variable_types:
pip
int [2]


decompiled_code:
__int64 shell_fg()
{
__int64 *v0; // rax
__int64 result; // rax

tcsetpgrp(0, SHIDWORD(qword_AD8));
tcsetattr(0, 1, (const struct termios *)(*(_QWORD *)rsh_pgroup + 176LL));
v0 = (__int64 *)rsh_pgroup;
*(_DWORD *)(*(_QWORD *)rsh_pgroup + 24LL) = 1;
result = *v0;
*(_DWORD *)(result + 20) = 0;
return result;
}

canonical_decompiled_code:
__int64 func3()
{
__int64 *v0; // rax
__int64 result; // rax

tcsetpgrp(0, SHIDWORD(qword_AD8));
tcsetattr(0, 1, (const struct termios *)(*(_QWORD *)rsh_pgroup + 176LL));
v0 = (__int64 *)rsh_pgroup;
*(_DWORD *)(*(_QWORD *)rsh_pgroup + 24LL) = 1;
result = *v0;
*(_DWORD *)(result + 20) = 0;
return result;
}

original_code:
void shell_fg(){
  tcsetpgrp(0, rsh_pgroup.pgid);
  tcsetattr(0, 1, &rsh_pgroup.pgroup[0]->term);
  rsh_pgroup.pgroup[0]->running = 1;
  rsh_pgroup.pgroup[0]->background = 0;
}


background

decompiled_code:
void __fastcall background(_DWORD *a1)
{
if ( a1[6] )
goto LABEL_2;
if ( !kill(-*a1, 18) )
{
a1[6] = 1;
LABEL_2:
a1[5] = 1;
return;
}
perror("kill()");
}

canonical_decompiled_code:
void __fastcall func4(_DWORD *a1)
{
if ( a1[6] )
goto LABEL_2;
if ( !kill(-*a1, 18) )
{
a1[6] = 1;
LABEL_2:
a1[5] = 1;
return;
}
perror("kill()");
}

original_code:
void background(struct rsh_process *proc){
  int err;
  if ( ! proc->running ){
    err = kill(-proc->pid, 18);
    if ( err ){
      perror("kill()");
      return;
    }
    proc->running = 1;
  }
  proc->background = 1;
}

variable_types: err int

user_defined_types: struct termios { unsigned int c_iflag; unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; }


decompiled_code:
void *get_empty_process()
{
int v0; // ebp
_QWORD *v1; // rax
int v2; // ebx
size_t v3; // rbx
void *v4; // rax
void *v5; // r12
void *v6; // r13

v0 = qword_AC8;
if ( (int)qword_AC8 <= 0 )
{
v2 = 0;
}
else
{
v1 = rsh_pgroup;
v2 = 0;
while ( *v1 )
{
++v2;
++v1;
if ( v2 == (_DWORD)qword_AC8 )
goto LABEL_5;
}
}
if ( (_DWORD)qword_AC8 != v2 )
goto LABEL_9;
v0 = v2;
LABEL_5:
v3 = 8LL * (v0 + 8);
v4 = malloc(v3);
v5 = v4;
if ( v4 )
{
memset(v4, 0, v3);
v6 = rsh_pgroup;
memcpy(v5, rsh_pgroup, v3 - 64);
free(v6);
rsh_pgroup = v5;
LODWORD(qword_AC8) = qword_AC8 + 8;
v2 = v0;
LABEL_9:
v5 = malloc(0x108uLL);
if ( v5 )
{
memset(v5, 0, 0x108uLL);
*((_QWORD *)rsh_pgroup + v2) = v5;
}
}
return v5;
}

canonical_decompiled_code:
void *func6()
{
int v0; // ebp
_QWORD *v1; // rax
int v2; // ebx
size_t v3; // rbx
void *v4; // rax
void *v5; // r12
void *v6; // r13

v0 = qword_AC8;
if ( (int)qword_AC8 <= 0 )
{
v2 = 0;
}
else
{
v1 = rsh_pgroup;
v2 = 0;
while ( *v1 )
{
++v2;
++v1;
if ( v2 == (_DWORD)qword_AC8 )
goto LABEL_5;
}
}
if ( (_DWORD)qword_AC8 != v2 )
goto LABEL_9;
v0 = v2;
LABEL_5:
v3 = 8LL * (v0 + 8);
v4 = malloc(v3);
v5 = v4;
if ( v4 )
{
memset(v4, 0, v3);
v6 = rsh_pgroup;
memcpy(v5, rsh_pgroup, v3 - 64);
free(v6);
rsh_pgroup = v5;
LODWORD(qword_AC8) = qword_AC8 + 8;
v2 = v0;
LABEL_9:
v5 = malloc(0x108uLL);
if ( v5 )
{
memset(v5, 0, 0x108uLL);
*((_QWORD *)rsh_pgroup + v2) = v5;
}
}
return v5;
}

original_code:
struct rsh_process *get_empty_process(){
  int i;
  struct rsh_process **tmp, *proc;
  for ( i = 0; i < rsh_pgroup.max_procs; i++)
    if ( rsh_pgroup.pgroup[i] == ((void *)0) ) break;
  if ( i == rsh_pgroup.max_procs ){
    tmp = (struct rsh_process **)
      malloc(sizeof(struct rsh_process *) * (rsh_pgroup.max_procs + 8));
    if ( ! tmp )
      return ((void *)0);
    memset(tmp, 0, sizeof(struct rsh_process *) * (rsh_pgroup.max_procs + 8));
    memcpy(tmp, rsh_pgroup.pgroup,
    sizeof(struct rsh_process *) *rsh_pgroup.max_procs);
    free(rsh_pgroup.pgroup);
    rsh_pgroup.pgroup = tmp;
    rsh_pgroup.max_procs += 8;
  }
  proc = (struct rsh_process *) malloc(sizeof(struct rsh_process) );
  if ( ! proc )
    return ((void *)0);
  memset(proc, 0, sizeof(struct rsh_process));
  rsh_pgroup.pgroup[i] = proc;
  return proc;
}

canonical_original_code:
struct rsh_process *get_empty_process(){
  int i;
  struct rsh_process **tmp; struct rsh_process *proc;
  for ( i = 0; i < rsh_pgroup.max_procs; i++)
    if ( rsh_pgroup.pgroup[i] == ((void *)0) ) break;
  if ( i == rsh_pgroup.max_procs ){
    tmp = (struct rsh_process **)
      malloc(sizeof(struct rsh_process *) * (rsh_pgroup.max_procs + 8));
    if ( ! tmp )
      return ((void *)0);
    memset(tmp, 0, sizeof(struct rsh_process *) * (rsh_pgroup.max_procs + 8));
    memcpy(tmp, rsh_pgroup.pgroup,
    sizeof(struct rsh_process *) *rsh_pgroup.max_procs);
    free(rsh_pgroup.pgroup);
    rsh_pgroup.pgroup = tmp;
    rsh_pgroup.max_procs += 8;
  }
  proc = (struct rsh_process *) malloc(sizeof(struct rsh_process) );
  if ( ! proc )
    return ((void *)0);
  memset(proc, 0, sizeof(struct rsh_process));
  rsh_pgroup.pgroup[i] = proc;
  return proc;
}

variable_types: i int

variable_types: struct rsh_process { int pid; unsigned int pgid; int stdin; int stdout; int stderr; int background; int running; char name[128]; int pipe[2]; int pipe_used; int pipe_lane; int display_exit; struct termios { unsigned int c_iflag; unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; } term; char *command; char **argv; int argc; } **


decompiled_code:
__int64 __fastcall get_next_proc(int *a1)
{
int v1; // eax
__int64 i; // rdx
__int64 v3; // rcx

v1 = *a1;
if ( *a1 >= (int)qword_AC8 )
return 0LL;
for ( i = 8LL * v1; ; i += 8LL )
{
v3 = *(_QWORD *)((char *)rsh_pgroup + i);
if ( v3 )
break;
*a1 = ++v1;
if ( v1 >= (int)qword_AC8 )
return v3;
}
*a1 = v1 + 1;
return v3;
}

canonical_decompiled_code:
__int64 __fastcall func7(int *a1)
{
int v1; // eax
__int64 i; // rdx
__int64 v3; // rcx

v1 = *a1;
if ( *a1 >= (int)qword_AC8 )
return 0LL;
for ( i = 8LL * v1; ; i += 8LL )
{
v3 = *(_QWORD *)((char *)rsh_pgroup + i);
if ( v3 )
break;
*a1 = ++v1;
if ( v1 >= (int)qword_AC8 )
return v3;
}
*a1 = v1 + 1;
return v3;
}

original_code:
struct rsh_process *get_next_proc(int *state){
  struct rsh_process *tmp = ((void *)0);
  for ( ; *state < rsh_pgroup.max_procs; (*state)++){
    if ( rsh_pgroup.pgroup[*state] ){
      tmp = rsh_pgroup.pgroup[*state];
      (*state)++;
      break;
    }
  }
  return tmp;
}

variable_types:
state
int *

return_type: struct rsh_process { int pid; unsigned int pgid; int stdin; int stdout; int stderr; int background; int running; char name[128]; int pipe[2]; int pipe_used; int pipe_lane; int display_exit; struct termios { unsigned int c_iflag; unsigned int c_oflag; unsigned int c_cflag; unsigned int c_lflag; unsigned char c_line; unsigned char c_cc[32]; unsigned int c_ispeed; unsigned int c_ospeed; } term; char *command; char **argv; int argc; } *


decompiled_code:
__pid_t *continue_running_procs()
{
__pid_t *result; // rax
int v1[3]; // [rsp+Ch] [rbp-Ch] BYREF

v1[0] = 0;
while ( 1 )
{
result = (__pid_t *)get_next_proc(v1);
if ( !result )
break;
if ( result[6] )
kill(*result, 18);
}
return result;
}

canonical_decompiled_code:
__pid_t *func8()
{
__pid_t *result; // rax
int v1[3]; // [rsp+Ch] [rbp-Ch] BYREF

v1[0] = 0;
while ( 1 )
{
result = (__pid_t *)func7(v1);
if ( !result )
break;
if ( result[6] )
kill(*result, 18);
}
return result;
}

original_code:
void continue_running_procs(){
  int state = 0;
  struct rsh_process *proc;
  while ( (proc = get_next_proc(&state)) != ((void *)0)){
    if ( proc->running ){
      kill(proc->pid, 18);
    }
  }
}


decompiled_code:
void __fastcall cleanup_proc(void *ptr)
{
__int64 v1; // rax
void **v2; // rdx

if ( *((_DWORD *)ptr + 41) )
{
close(*((_DWORD *)ptr + 39));
close(*((_DWORD *)ptr + 40));
}
free(ptr);
if ( (int)qword_AC8 > 0 )
{
v1 = 0LL;
do
{
v2 = (void **)((char *)rsh_pgroup + 8 * v1);
if ( *v2 == ptr )
*v2 = 0LL;
++v1;
}
while ( (int)qword_AC8 > (int)v1 );
}
}

canonical_decompiled_code:
void __fastcall func9(void *ptr)
{
__int64 v1; // rax
void **v2; // rdx

if ( *((_DWORD *)ptr + 41) )
{
close(*((_DWORD *)ptr + 39));
close(*((_DWORD *)ptr + 40));
}
free(ptr);
if ( (int)qword_AC8 > 0 )
{
v1 = 0LL;
do
{
v2 = (void **)((char *)rsh_pgroup + 8 * v1);
if ( *v2 == ptr )
*v2 = 0LL;
++v1;
}
while ( (int)qword_AC8 > (int)v1 );
}
}

original_code:
void cleanup_proc(struct rsh_process *proc){
  int i;
  if ( proc->pipe_used ){
    close(proc->pipe[0]);
    close(proc->pipe[1]);
  }
  free(proc);
  for ( i = 0; i < rsh_pgroup.max_procs; i++){
    if ( rsh_pgroup.pgroup[i] == proc )
      rsh_pgroup.pgroup[i] = ((void *)0);
  }
}


foreground

decompiled_code:
__int64 __fastcall foreground(void *ptr)
{
unsigned int v1; // ebx
__int16 v2; // bx
__int64 v3; // rdx
__pid_t v4; // eax
int v5; // ecx
int stat_loc; // [rsp+Ch] [rbp-1Ch] BYREF

tcsetpgrp(0, *((_DWORD *)ptr + 1));
tcsetattr(0, 1, &defaults);
if ( !*((_DWORD *)ptr + 6) )
{
if ( kill(-*(_DWORD *)ptr, 18) )
{
perror("kill()");
return (unsigned int)-1;
}
*((_DWORD *)ptr + 6) = 1;
}
*((_DWORD *)ptr + 5) = 0;
while ( 1 )
{
v4 = waitpid(*(_DWORD *)ptr, &stat_loc, 2);
v1 = v4;
v5 = interactive;
if ( interactive )
{
v2 = stat_loc;
v3 = stat_loc & 0x7F;
if ( (stat_loc & 0x7F) == 0 )
goto LABEL_15;
}
else
{
if ( v4 == -1 )
{
perror("waitpid()");
goto LABEL_16;
}
v2 = stat_loc;
v3 = stat_loc & 0x7F;
if ( (stat_loc & 0x7F) == 0 )
{
LABEL_15:
v1 = HIBYTE(v2);
cleanup_proc(ptr);
goto LABEL_16;
}
}
if ( !__OFSUB__((v2 & 0x7F) + 1, 1) && (v2 & 0x7F) != 0 )
break;
if ( (_BYTE)v2 != 127 )
{
v1 = -1;
goto LABEL_16;
}
*((_DWORD *)ptr + 6) = 0;
if ( v5 )
{
printf("\nProcess (%ld) stopped [sig=%d].\n", *(int *)ptr, HIBYTE(v2));
v1 = 0;
goto LABEL_16;
}
}
if ( interactive )
printf("\nProcess (%ld) terminated by signal (%d)\n", *(int *)ptr, v3);
stat_loc = BYTE1(stat_loc);
cleanup_proc(ptr);
v1 = 0;
LABEL_16:
shell_fg();
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func10(void *ptr)
{
unsigned int v1; // ebx
__int16 v2; // bx
__int64 v3; // rdx
__pid_t v4; // eax
int v5; // ecx
int stat_loc; // [rsp+Ch] [rbp-1Ch] BYREF

tcsetpgrp(0, *((_DWORD *)ptr + 1));
tcsetattr(0, 1, &defaults);
if ( !*((_DWORD *)ptr + 6) )
{
if ( kill(-*(_DWORD *)ptr, 18) )
{
perror("kill()");
return (unsigned int)-1;
}
*((_DWORD *)ptr + 6) = 1;
}
*((_DWORD *)ptr + 5) = 0;
while ( 1 )
{
v4 = waitpid(*(_DWORD *)ptr, &stat_loc, 2);
v1 = v4;
v5 = interactive;
if ( interactive )
{
v2 = stat_loc;
v3 = stat_loc & 0x7F;
if ( (stat_loc & 0x7F) == 0 )
goto LABEL_15;
}
else
{
if ( v4 == -1 )
{
perror("waitpid()");
goto LABEL_16;
}
v2 = stat_loc;
v3 = stat_loc & 0x7F;
if ( (stat_loc & 0x7F) == 0 )
{
LABEL_15:
v1 = HIBYTE(v2);
func9(ptr);
goto LABEL_16;
}
}
if ( !__OFSUB__((v2 & 0x7F) + 1, 1) && (v2 & 0x7F) != 0 )
break;
if ( (_BYTE)v2 != 127 )
{
v1 = -1;
goto LABEL_16;
}
*((_DWORD *)ptr + 6) = 0;
if ( v5 )
{
printf("\nProcess (%ld) stopped [sig=%d].\n", *(int *)ptr, HIBYTE(v2));
v1 = 0;
goto LABEL_16;
}
}
if ( interactive )
printf("\nProcess (%ld) terminated by signal (%d)\n", *(int *)ptr, v3);
stat_loc = BYTE1(stat_loc);
func9(ptr);
v1 = 0;
LABEL_16:
func3();
return v1;
}

original_code:
int foreground(struct rsh_process *proc){
  int err, status, ret = 0;
  tcsetpgrp(0, proc->pgid);
  tcsetattr(0, 1, &defaults);
  if ( ! proc->running ){
    err = kill(-proc->pid, 18);
    if ( err ){
      perror("kill()");
      return -1;
    }
    proc->running = 1;
  }
  proc->background = 0;
 rewait:
  err = waitpid(proc->pid, &status, 2);
  if ( interactive ){
    if ( (((status) & 0x7f) == 0) ){
      ret = (((status) & 0xff00) >> 8);
      cleanup_proc(proc);
      goto shell_foreground;
    }
  } else if ( err == -1 ){
    perror("waitpid()");
    ret = -1;
    goto shell_foreground;
  }
  if ( (((status) & 0x7f) == 0) ){
    ret = (((status) & 0xff00) >> 8);
    cleanup_proc(proc);
    goto shell_foreground;
  } else if ( (((signed char) (((status) & 0x7f) + 1) >> 1) > 0) ){
    if ( interactive )
      printf("\nProcess (%ld) terminated by signal (%d)\n",
      (long)proc->pid, ((status) & 0x7f));
    status = (((status) & 0xff00) >> 8);
    cleanup_proc(proc);
  } else if ( (((status) & 0xff) == 0x7f) ){
    proc->running = 0;
    if ( ! interactive )
      goto rewait;
    else
      printf("\nProcess (%ld) stopped [sig=%d].\n",
      (long)proc->pid, (((status) & 0xff00) >> 8));
  } else {
    ret = -1;
  }
 shell_foreground:
  shell_fg();
  return ret;
}

canonical_original_code:
int foreground(struct rsh_process *proc){
  int err; int status; int ret = 0;
  tcsetpgrp(0, proc->pgid);
  tcsetattr(0, 1, &defaults);
  if ( ! proc->running ){
    err = kill(-proc->pid, 18);
    if ( err ){
      perror("kill()");
      return -1;
    }
    proc->running = 1;
  }
  proc->background = 0;
 rewait:
  err = waitpid(proc->pid, &status, 2);
  if ( interactive ){
    if ( (((status) & 0x7f) == 0) ){
      ret = (((status) & 0xff00) >> 8);
      cleanup_proc(proc);
      goto shell_foreground;
    }
  } else if ( err == -1 ){
    perror("waitpid()");
    ret = -1;
    goto shell_foreground;
  }
  if ( (((status) & 0x7f) == 0) ){
    ret = (((status) & 0xff00) >> 8);
    cleanup_proc(proc);
    goto shell_foreground;
  } else if ( (((char) (((status) & 0x7f) + 1) >> 1) > 0) ){
    if ( interactive )
      printf("\nProcess (%ld) terminated by signal (%d)\n",
      (long)proc->pid, ((status) & 0x7f));
    status = (((status) & 0xff00) >> 8);
    cleanup_proc(proc);
  } else if ( (((status) & 0xff) == 0x7f) ){
    proc->running = 0;
    if ( ! interactive )
      goto rewait;
    else
      printf("\nProcess (%ld) stopped [sig=%d].\n",
      (long)proc->pid, (((status) & 0xff00) >> 8));
  } else {
    ret = -1;
  }
 shell_foreground:
  shell_fg();
  return ret;
}

variable_types: status int

variable_types: ret int


original_code:
int rsh_exec(char *command, int argc, char *argv[], int stdin, int stdout,
      int stderr, int background, int pipe_type, int pipe[2]){
  struct rsh_process *proc;
  proc = get_empty_process();
  if ( ! proc )
    return -1;
  memcpy(proc->name, command, 127);
  proc->name[127] = 0;
  proc->stdin = stdin;
  proc->stdout = stdout;
  proc->stderr = stderr;
  proc->command = command;
  proc->argv = argv;
  proc->argc = argc;
  proc->background = background;
  if ( pipe_type != 0x00 ){
    proc->pipe_used = 1;
    proc->pipe_lane = pipe_type;
    proc->pipe[0] = pipe[0];
    proc->pipe[1] = pipe[1];
  } else {
    proc->pipe_used = 0;
  }
  if ( pipe_type & (0x02|0x04) )
    proc->display_exit = 0;
  else
    proc->display_exit = 1;
  return _do_rsh_exec(proc);
}

variable_types:
command
char *

variable_types: argc int

variable_types:
argv
char *[]

variable_types: stdin int

variable_types: stdout int

variable_types: stderr int

variable_types: background int

variable_types:
pipe
int [2]


decompiled_code:
__pid_t *check_processes()
{
__pid_t *result; // rax
int *v1; // rbx
int stat_loc; // [rsp+8h] [rbp-10h] BYREF
int v3[3]; // [rsp+Ch] [rbp-Ch] BYREF

v3[0] = 0;
while ( 1 )
{
result = (__pid_t *)get_next_proc(v3);
v1 = result;
if ( !result )
return result;
if ( *result != (_DWORD)qword_AD8 && result[5] && waitpid(*result, &stat_loc, 3) > 0 )
{
if ( (stat_loc & 0x7F) == 0 )
{
if ( interactive )
{
if ( v1[43] )
{
printf("\nProcess (%ld) terminated (%d)\n", *v1, BYTE1(stat_loc));
rsh_reset_input();
}
}
goto LABEL_10;
}
if ( __OFSUB__((stat_loc & 0x7F) + 1, 1) || (stat_loc & 0x7F) == 0 )
{
if ( (_BYTE)stat_loc == 127 )
v1[6] = 0;
}
else
{
if ( interactive && v1[43] )
{
printf("\nProcess (%ld) terminated by signal (%d)\n", *v1, stat_loc & 0x7F);
rsh_reset_input();
}
LABEL_10:
cleanup_proc(v1);
}
}
}
}

canonical_decompiled_code:
__pid_t *func14()
{
__pid_t *result; // rax
int *v1; // rbx
int stat_loc; // [rsp+8h] [rbp-10h] BYREF
int v3[3]; // [rsp+Ch] [rbp-Ch] BYREF

v3[0] = 0;
while ( 1 )
{
result = (__pid_t *)func7(v3);
v1 = result;
if ( !result )
return result;
if ( *result != (_DWORD)qword_AD8 && result[5] && waitpid(*result, &stat_loc, 3) > 0 )
{
if ( (stat_loc & 0x7F) == 0 )
{
if ( interactive )
{
if ( v1[43] )
{
printf("\nProcess (%ld) terminated (%d)\n", *v1, BYTE1(stat_loc));
rsh_reset_input();
}
}
goto LABEL_10;
}
if ( __OFSUB__((stat_loc & 0x7F) + 1, 1) || (stat_loc & 0x7F) == 0 )
{
if ( (_BYTE)stat_loc == 127 )
v1[6] = 0;
}
else
{
if ( interactive && v1[43] )
{
printf("\nProcess (%ld) terminated by signal (%d)\n", *v1, stat_loc & 0x7F);
rsh_reset_input();
}
LABEL_10:
func9(v1);
}
}
}
}

original_code:
void check_processes(){
  int state = 0;
  int status, ret;
  struct rsh_process *proc;
  while ( (proc = get_next_proc(&state)) != ((void *)0) ){
    if ( proc->pid == rsh_pgroup.pid )
      continue;
    if ( ! proc->background )
      continue;
    ret = waitpid(proc->pid, &status, 1|2);
    if ( ret == 0 )
      continue;
    if ( ret < 0 ){
      continue;
    }
    if ( (((status) & 0x7f) == 0) ){
      if ( interactive && proc->display_exit ){
 printf("\nProcess (%ld) terminated (%d)\n",
        (long)proc->pid, (((status) & 0xff00) >> 8));
 rsh_reset_input();
      }
      cleanup_proc(proc);
    } else if ( (((signed char) (((status) & 0x7f) + 1) >> 1) > 0) ){
      if ( interactive && proc->display_exit ){
 printf("\nProcess (%ld) terminated by signal (%d)\n",
        (long)proc->pid, ((status) & 0x7f));
 rsh_reset_input();
      }
      cleanup_proc(proc);
    } else if ( (((status) & 0xff) == 0x7f) ){
      proc->running = 0;
    }
  }
}

canonical_original_code:
void check_processes(){
  int state = 0;
  int status; int ret;
  struct rsh_process *proc;
  while ( (proc = get_next_proc(&state)) != ((void *)0) ){
    if ( proc->pid == rsh_pgroup.pid )
      continue;
    if ( ! proc->background )
      continue;
    ret = waitpid(proc->pid, &status, 1|2);
    if ( ret == 0 )
      continue;
    if ( ret < 0 ){
      continue;
    }
    if ( (((status) & 0x7f) == 0) ){
      if ( interactive && proc->display_exit ){
 printf("\nProcess (%ld) terminated (%d)\n",
        (long)proc->pid, (((status) & 0xff00) >> 8));
 rsh_reset_input();
      }
      cleanup_proc(proc);
    } else if ( (((char) (((status) & 0x7f) + 1) >> 1) > 0) ){
      if ( interactive && proc->display_exit ){
 printf("\nProcess (%ld) terminated by signal (%d)\n",
        (long)proc->pid, ((status) & 0x7f));
 rsh_reset_input();
      }
      cleanup_proc(proc);
    } else if ( (((status) & 0xff) == 0x7f) ){
      proc->running = 0;
    }
  }
}

variable_types: state int


decompiled_code:
void clear_argv()
{
void *v0; // rax
void *v1; // rdi
__int64 v2; // rbx

v0 = argv;
if ( argv )
{
v1 = *(void **)argv;
if ( !*(_QWORD *)argv )
goto LABEL_6;
v2 = 8LL;
do
{
free(v1);
v0 = argv;
v1 = *(void **)((char *)argv + v2);
v2 += 8LL;
}
while ( v1 );
if ( argv )
LABEL_6:
free(v0);
}
argv = 0LL;
if ( command )
free(command);
command = 0LL;
proc_stdin = 0;
proc_stdout = 1;
proc_stderr = 2;
command_state = 0;
}

canonical_decompiled_code:
void func0()
{
void *v0; // rax
void *v1; // rdi
__int64 v2; // rbx

v0 = argv;
if ( argv )
{
v1 = *(void **)argv;
if ( !*(_QWORD *)argv )
goto LABEL_6;
v2 = 8LL;
do
{
free(v1);
v0 = argv;
v1 = *(void **)((char *)argv + v2);
v2 += 8LL;
}
while ( v1 );
if ( argv )
LABEL_6:
free(v0);
}
argv = 0LL;
if ( command )
free(command);
command = 0LL;
proc_stdin = 0;
proc_stdout = 1;
proc_stderr = 2;
command_state = 0;
}

original_code:
void clear_argv(){
  int i = 0;
  if ( argv ){
    while ( argv[i] != ((void *)0) )
      free(argv[i++]);
  }
  if ( argv )
    free(argv);
  argv = ((void *)0);
  if ( command )
    free(command);
  command = ((void *)0);
  proc_stdin = 0;
  proc_stdout = 1;
  proc_stderr = 2;
  command_state = 0;
}


decompiled_code:
__int64 __fastcall dispatch_process(unsigned int a1)
{
__int64 v1; // rax
unsigned int v2; // ebx

v1 = rsh_identify_builtin(command);
if ( v1 )
v2 = (*(__int64 (__fastcall **)(_QWORD, void *, _QWORD, _QWORD, _QWORD))(v1 + 8))(
(unsigned int)argc,
argv,
(unsigned int)proc_stdin,
(unsigned int)proc_stdout,
(unsigned int)proc_stderr);
else
v2 = rsh_exec(
command,
(unsigned int)argc,
argv,
(unsigned int)proc_stdin,
(unsigned int)proc_stdout,
(unsigned int)proc_stderr,
a1,
(unsigned int)pipe_status,
pipe_fds);
clear_argv();
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func1(unsigned int a1)
{
__int64 v1; // rax
unsigned int v2; // ebx

v1 = rsh_identify_builtin(command);
if ( v1 )
v2 = (*(__int64 (__fastcall **)(_QWORD, void *, _QWORD, _QWORD, _QWORD))(v1 + 8))(
(unsigned int)argc,
argv,
(unsigned int)proc_stdin,
(unsigned int)proc_stdout,
(unsigned int)proc_stderr);
else
v2 = rsh_exec(
command,
(unsigned int)argc,
argv,
(unsigned int)proc_stdin,
(unsigned int)proc_stdout,
(unsigned int)proc_stderr,
a1,
(unsigned int)pipe_status,
pipe_fds);
func0();
return v2;
}

original_code:
int dispatch_process(int background){
  int status;
  struct builtin *bin;
  bin = rsh_identify_builtin(command);
  if ( bin ){
    status = bin->func(argc, argv, proc_stdin, proc_stdout, proc_stderr);
    clear_argv();
    return status;
  }
  status = rsh_exec(command, argc, argv,
      proc_stdin, proc_stdout, proc_stderr, background,
      pipe_status, pipe_fds);
  clear_argv();
  return status;
}

variable_types: struct builtin { char *name; int (*func)(int argc, char **argv, int in, int out, int err); } *


decompiled_code:
void __fastcall append_to_argv(__int64 a1)
{
void *v1; // r12
int v2; // eax
size_t v3; // rbp
void *v4; // r13

if ( a1 )
{
v1 = argv;
if ( argv )
{
if ( argc + 1 >= max_argc )
{
v3 = 8LL * (max_argc + 8);
v4 = malloc(v3);
memcpy(v4, v1, v3 - 64);
free(v1);
argv = v4;
max_argc += 8;
}
}
else
{
argv = malloc(0x40uLL);
argc = 0;
max_argc = 8;
}
v2 = argc++;
*((_QWORD *)argv + v2) = a1;
*((_QWORD *)argv + argc) = 0LL;
}
}

canonical_decompiled_code:
void __fastcall func2(__int64 a1)
{
void *v1; // r12
int v2; // eax
size_t v3; // rbp
void *v4; // r13

if ( a1 )
{
v1 = argv;
if ( argv )
{
if ( argc + 1 >= max_argc )
{
v3 = 8LL * (max_argc + 8);
v4 = malloc(v3);
memcpy(v4, v1, v3 - 64);
free(v1);
argv = v4;
max_argc += 8;
}
}
else
{
argv = malloc(0x40uLL);
argc = 0;
max_argc = 8;
}
v2 = argc++;
*((_QWORD *)argv + v2) = a1;
*((_QWORD *)argv + argc) = 0LL;
}
}

original_code:
void append_to_argv(char *arg){
  char **tmp;
  if ( ! arg ) return;
  if ( ! argv ){
    argv = (char **)malloc(sizeof(char *) * 8 );
    argc = 0;
    max_argc = 8;
  }
  if ( (argc + 1) >= max_argc ){
    tmp = (char **)malloc( sizeof(char *) * (8 + max_argc) );
    memcpy(tmp, argv, max_argc * sizeof(char *) );
    free(argv);
    argv = tmp;
    max_argc += 8;
  }
  argv[argc++] = arg;
  argv[argc] = ((void *)0);
}

variable_types:
arg
char *

variable_types:
tmp
char **


decompiled_code:
__int64 __fastcall set_stdin(__int64 a1)
{
int v1; // eax
__int64 result; // rax

v1 = rsh_open(a1, 0LL, 0LL);
if ( v1 < 0 )
{
perror("rsh_open()");
result = 0xFFFFFFFFLL;
}
else
{
proc_stdin = v1;
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
int v1; // eax
__int64 result; // rax

v1 = rsh_open(a1, 0LL, 0LL);
if ( v1 < 0 )
{
perror("rsh_open()");
result = 0xFFFFFFFFLL;
}
else
{
proc_stdin = v1;
result = 0LL;
}
return result;
}

original_code:
int set_stdin(char *file){
  int fd;
  fd = rsh_open(file, 00, 0);
  if ( fd < 0 ){
    perror("rsh_open()");
    return -1;
  }
  proc_stdin = fd;
  return 0;
}

variable_types:
file
char *

variable_types: fd int


decompiled_code:
__int64 __fastcall set_stdout(__int64 a1, int a2)
{
int v2; // eax
__int64 result; // rax

v2 = rsh_open(a1, a2 == 0 ? 65 : 1089, 438LL);
if ( v2 < 0 )
{
perror("rsh_open()");
result = 0xFFFFFFFFLL;
}
else
{
proc_stdout = v2;
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(__int64 a1, int a2)
{
int v2; // eax
__int64 result; // rax

v2 = rsh_open(a1, a2 == 0 ? 65 : 1089, 438LL);
if ( v2 < 0 )
{
perror("rsh_open()");
result = 0xFFFFFFFFLL;
}
else
{
proc_stdout = v2;
result = 0LL;
}
return result;
}

original_code:
int set_stdout(char *file, int append){
  int fd;
  int flags = 0100|01;
  mode_t mode = 0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3);
  if ( append )
    flags |= 02000;
  fd = rsh_open(file, flags, mode);
  if ( fd < 0 ){
    perror("rsh_open()");
    return -1;
  }
  proc_stdout = fd;
  return 0;
}

canonical_original_code:
int set_stdout(char *file, int append){
  int fd;
  int flags = 0100|01;
  unsigned int mode = 0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3);
  if ( append )
    flags |= 02000;
  fd = rsh_open(file, flags, mode);
  if ( fd < 0 ){
    perror("rsh_open()");
    return -1;
  }
  proc_stdout = fd;
  return 0;
}

variable_types: append int

variable_types: flags int

variable_types:
mode
unsigned int


decompiled_code:
__int64 __fastcall set_stderr(__int64 a1, int a2)
{
int v2; // eax
__int64 result; // rax

v2 = rsh_open(a1, a2 == 0 ? 65 : 1089, 438LL);
if ( v2 < 0 )
{
perror("rsh_open()");
result = 0xFFFFFFFFLL;
}
else
{
proc_stderr = v2;
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(__int64 a1, int a2)
{
int v2; // eax
__int64 result; // rax

v2 = rsh_open(a1, a2 == 0 ? 65 : 1089, 438LL);
if ( v2 < 0 )
{
perror("rsh_open()");
result = 0xFFFFFFFFLL;
}
else
{
proc_stderr = v2;
result = 0LL;
}
return result;
}

original_code:
int set_stderr(char *file, int append){
  int fd;
  int flags = 0100|01;
  mode_t mode = 0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3);
  if ( append )
    flags |= 02000;
  fd = rsh_open(file, flags, mode);
  if ( fd < 0 ){
    perror("rsh_open()");
    return -1;
  }
  proc_stderr = fd;
  return 0;
}

canonical_original_code:
int set_stderr(char *file, int append){
  int fd;
  int flags = 0100|01;
  unsigned int mode = 0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3);
  if ( append )
    flags |= 02000;
  fd = rsh_open(file, flags, mode);
  if ( fd < 0 ){
    perror("rsh_open()");
    return -1;
  }
  proc_stderr = fd;
  return 0;
}


decompiled_code:
__int64 __fastcall rsh_command(const char **a1)
{
const char *v2; // rdi
__int64 v3; // rbp
unsigned int v4; // ebp

clear_argv();
while ( 2 )
{
switch ( *((_DWORD *)a1 + 2) )
{
case 0:
v4 = command_state;
if ( command_state )
{
if ( (pipe_status & 6) != 0 )
pipe_status = 1;
v4 = dispatch_process(0);
clear_argv();
pipe_status = 0;
}
return v4;
case 1:
v2 = *a1;
if ( *a1 )
{
if ( command_state == 1 )
{
append_to_argv((__int64)v2);
}
else
{
command = strdup(v2);
append_to_argv((__int64)*a1);
command_state = 1;
}
}
goto LABEL_57;
case 2:
v3 = (__int64)*a1;
*(_BYTE *)(v3 + strlen(*a1) - 1) = 0;
if ( *((_DWORD *)a1 + 6) == 1 )
{
symtable_add(*a1, a1[2]);
a1 += 2;
}
else
{
symtable_add(*a1, 0LL);
}
goto LABEL_57;
case 0xB:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = set_stdin((__int64)*a1);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xC:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = set_stdout((__int64)*a1, 0);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xD:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = set_stderr((__int64)*a1, 0);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xE:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = set_stdout((__int64)*a1, 1);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xF:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( *((_DWORD *)a1 + 2) )
{
v4 = set_stderr((__int64)*a1, 1);
if ( v4 == -1 )
return v4;
LABEL_57:
a1 += 2;
continue;
}
LABEL_43:
puts("Syntax error: missing redirect destination.");
return (unsigned int)-1;
case 0x10:
if ( !*((_DWORD *)a1 + 6) )
goto LABEL_47;
if ( pipe(pipe_fds) < 0 )
goto LABEL_48;
proc_stdout = pipe_fds[1];
pipe_status |= 2u;
dispatch_process(1u);
clear_argv();
proc_stdin = pipe_fds[0];
goto LABEL_57;
case 0x11:
if ( !*((_DWORD *)a1 + 6) )
{
LABEL_47:
puts("Missing read half of pipe command.");
return (unsigned int)-1;
}
if ( pipe(pipe_fds) < 0 )
{
LABEL_48:
perror("pipe");
return (unsigned int)-1;
}
proc_stdout = pipe_fds[1];
pipe_status |= 4u;
dispatch_process(1u);
clear_argv();
proc_stdin = pipe_fds[0];
goto LABEL_57;
case 0x15:
if ( (pipe_status & 6) != 0 )
pipe_status = 1;
dispatch_process(1u);
clear_argv();
pipe_status = 0;
goto LABEL_57;
default:
goto LABEL_57;
}
}
}

canonical_decompiled_code:
__int64 __fastcall func6(const char **a1)
{
const char *v2; // rdi
__int64 v3; // rbp
unsigned int v4; // ebp

func0();
while ( 2 )
{
switch ( *((_DWORD *)a1 + 2) )
{
case 0:
v4 = command_state;
if ( command_state )
{
if ( (pipe_status & 6) != 0 )
pipe_status = 1;
v4 = func1(0);
func0();
pipe_status = 0;
}
return v4;
case 1:
v2 = *a1;
if ( *a1 )
{
if ( command_state == 1 )
{
func2((__int64)v2);
}
else
{
command = strdup(v2);
func2((__int64)*a1);
command_state = 1;
}
}
goto LABEL_57;
case 2:
v3 = (__int64)*a1;
*(_BYTE *)(v3 + strlen(*a1) - 1) = 0;
if ( *((_DWORD *)a1 + 6) == 1 )
{
symtable_add(*a1, a1[2]);
a1 += 2;
}
else
{
symtable_add(*a1, 0LL);
}
goto LABEL_57;
case 0xB:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = func3((__int64)*a1);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xC:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = func4((__int64)*a1, 0);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xD:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = func5((__int64)*a1, 0);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xE:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( !*((_DWORD *)a1 + 2) )
goto LABEL_43;
v4 = func4((__int64)*a1, 1);
if ( v4 == -1 )
return v4;
goto LABEL_57;
case 0xF:
if ( *((_DWORD *)a1 + 6) == 18 )
a1 += 4;
else
a1 += 2;
if ( *((_DWORD *)a1 + 2) )
{
v4 = func5((__int64)*a1, 1);
if ( v4 == -1 )
return v4;
LABEL_57:
a1 += 2;
continue;
}
LABEL_43:
puts("Syntax error: missing redirect destination.");
return (unsigned int)-1;
case 0x10:
if ( !*((_DWORD *)a1 + 6) )
goto LABEL_47;
if ( pipe(pipe_fds) < 0 )
goto LABEL_48;
proc_stdout = pipe_fds[1];
pipe_status |= 2u;
func1(1u);
func0();
proc_stdin = pipe_fds[0];
goto LABEL_57;
case 0x11:
if ( !*((_DWORD *)a1 + 6) )
{
LABEL_47:
puts("Missing read half of pipe command.");
return (unsigned int)-1;
}
if ( pipe(pipe_fds) < 0 )
{
LABEL_48:
perror("pipe");
return (unsigned int)-1;
}
proc_stdout = pipe_fds[1];
pipe_status |= 4u;
func1(1u);
func0();
proc_stdin = pipe_fds[0];
goto LABEL_57;
case 0x15:
if ( (pipe_status & 6) != 0 )
pipe_status = 1;
func1(1u);
func0();
pipe_status = 0;
goto LABEL_57;
default:
goto LABEL_57;
}
}
}

original_code:
int rsh_command(struct rsh_token *seq){
  int ret;
  clear_argv();
  while ( 1 ){
    switch (seq->type){
    case 1:
      if ( ! seq->tok )
 break;
      if ( command_state == 1 ){
 append_to_argv(seq->tok);
      } else {
 command = strdup(seq->tok);
 append_to_argv(seq->tok);
 command_state = 1;
      }
      break;
    case 2:
      seq->tok[strlen(seq->tok)-1] = 0;
      if ( (seq+1)->type == 1 ){
 symtable_add(seq->tok, (seq+1)->tok);
 seq++;
      } else {
 symtable_add(seq->tok, ((void *)0));
      }
      break;
    case 11:
      seq++;
      if ( seq->type == 18 )
 seq++;
      if ( seq->type == 0 ){
 printf("Syntax error: missing redirect destination.\n");
 return -1;
      }
      if ( set_stdin(seq->tok) == -1 )
 return -1;
      break;
    case 12:
      seq++;
      if ( seq->type == 18 )
 seq++;
      if ( seq->type == 0 ){
 printf("Syntax error: missing redirect destination.\n");
 return -1;
      }
      if ( set_stdout(seq->tok, 0) == -1 )
 return -1;
      break;
    case 13:
      seq++;
      if ( seq->type == 18 )
 seq++;
      if ( seq->type == 0 ){
 printf("Syntax error: missing redirect destination.\n");
 return -1;
      }
      if ( set_stderr(seq->tok, 0) == -1 )
 return -1;
      break;
    case 14:
      seq++;
      if ( seq->type == 18 )
 seq++;
      if ( seq->type == 0 ){
 printf("Syntax error: missing redirect destination.\n");
 return -1;
      }
      if ( set_stdout(seq->tok, 1) == -1 )
 return -1;
      break;
    case 15:
      seq++;
      if ( seq->type == 18 )
 seq++;
      if ( seq->type == 0 ){
 printf("Syntax error: missing redirect destination.\n");
 return -1;
      }
      if ( set_stderr(seq->tok, 1) == -1 )
 return -1;
      break;
    case 16:
      if ( (seq+1)->type == 0 ){
 printf("Missing read half of pipe command.\n");
 return -1;
      }
      ret = pipe(pipe_fds);
      if ( ret < 0 ){
 perror("pipe");
 return -1;
      }
      proc_stdout = pipe_fds[1];
      pipe_status |= 0x02;
      dispatch_process(1);
      clear_argv();
      proc_stdin = pipe_fds[0];
      break;
    case 17:
      if ( (seq+1)->type == 0 ){
 printf("Missing read half of pipe command.\n");
 return -1;
      }
      ret = pipe(pipe_fds);
      if ( ret < 0 ){
 perror("pipe");
 return -1;
      }
      proc_stdout = pipe_fds[1];
      pipe_status |= 0x04;
      dispatch_process(1);
      clear_argv();
      proc_stdin = pipe_fds[0];
      break;
    case 21:
      if ( pipe_status & (0x02|0x04) )
 pipe_status = 0x01;
      dispatch_process(1);
      clear_argv();
      pipe_status = 0x00;
      break;
    case 0:
      if ( command_state != 0){
 if ( pipe_status & (0x02|0x04) )
   pipe_status = 0x01;
 ret = dispatch_process(0);
 clear_argv();
 pipe_status = 0x00;
 return ret;
      } else {
 return 0;
      }
    }
    seq++;
  }
  return 0;
}

variable_types: struct rsh_token { char *tok; int type; } *

variable_types: ret int


decompiled_code:
__int64 run_script()
{
_QWORD *v0; // rbx
unsigned int v1; // ebp
__int64 v2; // rax
void *v3; // rbx
char s[30]; // [rsp+Ah] [rbp-1Eh] BYREF

v0 = (_QWORD *)script_argv;
symtable_add(&unk_D4, script);
if ( *v0 )
{
v1 = 1;
do
{
snprintf(s, 6uLL, "%d", v1);
symtable_add(s, *v0++);
++v1;
}
while ( *v0 );
}
while ( 1 )
{
v2 = read_next_statement();
v3 = (void *)v2;
if ( !v2 )
break;
exec_token_seq(v2);
free(v3);
}
return 0LL;
}

canonical_decompiled_code:
__int64 func0()
{
_QWORD *v0; // rbx
unsigned int v1; // ebp
__int64 v2; // rax
void *v3; // rbx
char s[30]; // [rsp+Ah] [rbp-1Eh] BYREF

v0 = (_QWORD *)script_argv;
symtable_add(&unk_D4, script);
if ( *v0 )
{
v1 = 1;
do
{
snprintf(s, 6uLL, "%d", v1);
symtable_add(s, *v0++);
++v1;
}
while ( *v0 );
}
while ( 1 )
{
v2 = read_next_statement();
v3 = (void *)v2;
if ( !v2 )
break;
exec_token_seq(v2);
free(v3);
}
return 0LL;
}

original_code:
int run_script(){
  struct rsh_token *tokens;
  char buf[6];
  char **argv = script_argv;
  int argc = 1;
  symtable_add("0", script);
  while ( *argv != ((void *)0)){
    snprintf(buf, 6, "%d", argc);
    symtable_add(buf, *argv);
    argv++;
    argc++;
  }
  while ( ( tokens = read_next_statement()) != ((void *)0) ){
    exec_token_seq(tokens);
    free(tokens);
  }
  return 0;
}

variable_types:
buf
char [6]

variable_types:
argv
char **

variable_types: argc int

user_defined_types: struct rsh_token { char *tok; int type; }


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

while ( 1 )
{
prompt_print();
v0 = read_next_statement();
if ( !v0 )
break;
exec_token_seq(v0);
}
return 0LL;
}

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

while ( 1 )
{
prompt_print();
v0 = read_next_statement();
if ( !v0 )
break;
exec_token_seq(v0);
}
return 0LL;
}

original_code:
int run_interactive(){
  struct rsh_token *tokens;
  do {
    prompt_print();
    tokens = read_next_statement();
    if ( ! tokens )
      break;
    exec_token_seq(tokens);
  } while (1);
  return 0;
}


decompiled_code:
__int64 sigchld_handler()
{
return check_processes();
}

canonical_decompiled_code:
__int64 func2()
{
return check_processes();
}

original_code:
void sigchld_handler(int sig){
  check_processes();
}

variable_types: sig int


decompiled_code:
__uid_t prompt_init()
{
__uid_t result; // eax

symtable_add("PROMPT", "[\\u@\\h \\W]$ ");
result = geteuid();
euid = result;
return result;
}

canonical_decompiled_code:
__uid_t func0()
{
__uid_t result; // eax

symtable_add("PROMPT", "[\\u@\\h \\W]$ ");
result = geteuid();
euid = result;
return result;
}

original_code:
void prompt_init(){
  symtable_add("PROMPT", "[\\u@\\h \\W]$ ");
  euid = geteuid();
}


decompiled_code:
int prompt_print()
{
_BYTE *v0; // rax
_BYTE *v1; // rbx
char i; // di
int result; // eax
_BYTE *v4; // rbp

v0 = (_BYTE *)symtable_get("PROMPT");
if ( v0 )
{
v1 = v0;
for ( i = *v0; i; i = v4[1] )
{
if ( i == 92 )
{
v4 = v1 + 1;
if ( v1[1] == 36 )
{
if ( euid )
putchar(36);
else
putchar(35);
}
else
{
putchar(94);
}
}
else
{
putchar(i);
v4 = v1;
}
v1 = v4 + 1;
}
printf("%s", v1);
result = fflush(stdout);
}
else
{
printf("> ");
result = fflush(stdout);
}
return result;
}

canonical_decompiled_code:
int func6()
{
_BYTE *v0; // rax
_BYTE *v1; // rbx
char i; // di
int result; // eax
_BYTE *v4; // rbp

v0 = (_BYTE *)symtable_get("PROMPT");
if ( v0 )
{
v1 = v0;
for ( i = *v0; i; i = v4[1] )
{
if ( i == 92 )
{
v4 = v1 + 1;
if ( v1[1] == 36 )
{
if ( euid )
putchar(36);
else
putchar(35);
}
else
{
putchar(94);
}
}
else
{
putchar(i);
v4 = v1;
}
v1 = v4 + 1;
}
printf("%s", v1);
result = fflush(stdout);
}
else
{
printf("> ");
result = fflush(stdout);
}
return result;
}

original_code:
void prompt_print(){
  char *prompt = symtable_get("PROMPT");
  if ( ! prompt ){
    printf("> ");
    fflush(stdout);
    return;
  }
  while ( *prompt ){
    if ( *prompt == '\\' ){
      prompt++;
      switch ( *prompt ){
      case '\\':
 printf("/");
 break;
      case 'u':
 _display_user_name();
 break;
      case 'W':
 _display_cwd();
 break;
      case 's':
 _display_shell_name();
 break;
      case 'H':
 _display_hostname();
 break;
      case 'h':
 _display_short_hostname();
 break;
      case 'e':
 break;
      case '$':
 if ( euid == 0 )
   printf("#");
 else
   printf("$");
 break;
      default:
 printf("^");
 break;
      }
    } else {
      printf("%c", *prompt);
    }
    prompt++;
  }
  printf("%s", prompt);
  fflush(stdout);
}

variable_types:
prompt
char *


decompiled_code:
__int64 __fastcall rsh_native_path(char *s1)
{
const char *v2; // rbp
size_t v3; // rax

if ( *s1 != 47 )
return (unsigned int)native;
v2 = rsh_root;
v3 = strlen(rsh_root);
return strncmp(s1, v2, v3) != 0;
}

canonical_decompiled_code:
__int64 __fastcall func0(char *s1)
{
const char *v2; // rbp
size_t v3; // rax

if ( *s1 != 47 )
return (unsigned int)native;
v2 = rsh_root;
v3 = strlen(rsh_root);
return strncmp(s1, v2, v3) != 0;
}

original_code:
int rsh_native_path(const char *path){
  if ( *path != '/' )
    return native;
  if ( strncmp(path, rsh_root, strlen(rsh_root)) )
    return 1;
  return 0;
}

canonical_original_code:
int rsh_native_path(char *path){
  if ( *path != '/' )
    return native;
  if ( strncmp(path, rsh_root, strlen(rsh_root)) )
    return 1;
  return 0;
}

variable_types:
path
char *


decompiled_code:
size_t __fastcall rsh_builtin_path(__int64 a1)
{
return a1 + strlen(rsh_root);
}

canonical_decompiled_code:
size_t __fastcall func1(__int64 a1)
{
return a1 + strlen(rsh_root);
}

original_code:
char *rsh_builtin_path(char *path){
  return path + strlen(rsh_root);
}


decompiled_code:
ssize_t __fastcall rsh_read(__int16 a1, void *a2, size_t a3)
{
ssize_t result; // rax

if ( (a1 & 0x8000) != 0 )
result = rsh_read();
else
result = read(a1, a2, a3);
return result;
}

canonical_decompiled_code:
ssize_t __fastcall func2(__int16 a1, void *a2, size_t a3)
{
ssize_t result; // rax

if ( (a1 & 0x8000) != 0 )
result = func2();
else
result = read(a1, a2, a3);
return result;
}

original_code:
ssize_t rsh_read(int fd, void *buf, size_t count){
  if ( ! ( fd & 0x8000 ) )
    return read(fd, buf, count);
  else
    return _rsh_read(fd, buf, count);
}

canonical_original_code:
long rsh_read(int fd, void *buf, unsigned long count){
  if ( ! ( fd & 0x8000 ) )
    return read(fd, buf, count);
  else
    return _rsh_read(fd, buf, count);
}

variable_types:
buf
void *

variable_types:
count
unsigned long


decompiled_code:
ssize_t __fastcall rsh_write(__int16 a1, const void *a2, size_t a3)
{
ssize_t result; // rax

if ( (a1 & 0x8000) != 0 )
result = rsh_write();
else
result = write(a1, a2, a3);
return result;
}

canonical_decompiled_code:
ssize_t __fastcall func3(__int16 a1, const void *a2, size_t a3)
{
ssize_t result; // rax

if ( (a1 & 0x8000) != 0 )
result = func3();
else
result = write(a1, a2, a3);
return result;
}

original_code:
ssize_t rsh_write(int fd, const void *buf, size_t count){
  if ( ! ( fd & 0x8000 ) )
    return write(fd, buf, count);
  else
    return _rsh_write(fd, buf, count);
}

canonical_original_code:
long rsh_write(int fd, void *buf, unsigned long count){
  if ( ! ( fd & 0x8000 ) )
    return write(fd, buf, count);
  else
    return _rsh_write(fd, buf, count);
}


decompiled_code:
__int64 rsh_dprintf(__int16 a1, const char *a2, ...)
{
int v2; // ebx
char v4[520]; // [rsp+0h] [rbp-2E8h] BYREF
gcc_va_list arg; // [rsp+208h] [rbp-E0h] BYREF

va_start(arg, a2);
vsnprintf(v4, 0x200uLL, a2, arg);
v2 = strlen(v4);
return (unsigned int)-(v2 != (unsigned int)rsh_write(a1, v4, v2));
}

canonical_decompiled_code:
__int64 func4(__int16 a1, const char *a2, ...)
{
int v2; // ebx
char v4[520]; // [rsp+0h] [rbp-2E8h] BYREF
gcc_va_list arg; // [rsp+208h] [rbp-E0h] BYREF

va_start(arg, a2);
vsnprintf(v4, 0x200uLL, a2, arg);
v2 = strlen(v4);
return (unsigned int)-(v2 != (unsigned int)func3(a1, v4, v2));
}

original_code:
int rsh_dprintf(int fd, char *format, ...){
  va_list args;
  char buf[512];
  int len;
  int written;
  __builtin_va_start(args,format);
  vsnprintf(buf, 512, format, args);
  len = strlen(buf);
  written = rsh_write(fd, buf, len);
  if ( written != len )
    return -1;
  return 0;
}

canonical_original_code:
int rsh_dprintf(int fd, char *format, ...){
  __builtin_va_list args;
  char buf[512];
  int len;
  int written;
  __builtin_va_start(args,format);
  vsnprintf(buf, 512, format, args);
  len = strlen(buf);
  written = rsh_write(fd, buf, len);
  if ( written != len )
    return -1;
  return 0;
}

variable_types:
format
char *

variable_types:
buf
char [512]

variable_types: len int

variable_types: written int