user: 请将以下的汇编代码转换成C语言代码:

```asm
<sh>:
  endbr64
  push   %r15
  push   %r14
  lea    D38(%rip),%r14
  push   %r13
  mov    %edi,%r13d
  push   %r12
  push   %rbp
  push   %rbx
  mov    %esi,%ebx
  sub    $0x8,%rsp
  jmp    L32
  nopl   0x0(%rax,%rax,1)
L49:
  mov    %r13d,%edi
  xor    %eax,%eax
  call   <readline@plt>
  movslq %eax,%rbp
  test   %eax,%eax
  je     L132
  mov    %rbp,%rdi
  call   <strlen@plt>
  mov    %rbp,%rdi
  mov    %rax,%rsi
  xor    %eax,%eax
  call   <tokenize@plt>
  movslq %eax,%r12
  test   %eax,%eax
  je     L111
  mov    (%r12),%r15
  test   %r15,%r15
  je     L79
  mov    %r14,%rsi
  mov    %r15,%rdi
  call   <strcmp@plt>
  test   %eax,%eax
  je     L40
  cmpb   $0x63,(%r15)
  je     L57
L135:
  call   <fork@plt>
  test   %eax,%eax
  je     L109
  xor    %edi,%edi
  xor    %eax,%eax
  call   <wait@plt>
  nopl   0x0(%rax)
L79:
  mov    %rbp,%rdi
  call   <free@plt>
  mov    %r12,%rdi
  call   <free@plt>
L32:
  test   %ebx,%ebx
  je     L49
  lea    D67(%rip),%rsi
  mov    $0x1,%edi
  xor    %eax,%eax
  call   <writestr@plt>
  jmp    L49
  nopl   0x0(%rax,%rax,1)
L111:
  lea    D63(%rip),%rsi
  mov    $0x2,%edi
  call   <writestr@plt>
  jmp    L79
  nopl   0x0(%rax,%rax,1)
L57:
  cmpb   $0x64,0x1(%r15)
  jne    L135
  cmpb   $0x0,0x2(%r15)
  jne    L135
  mov    0x8(%r12),%rdi
  test   %rdi,%rdi
  je     L34
  xor    %eax,%eax
  call   <chdir@plt>
  jmp    L79
  nopl   0x0(%rax)
L34:
  xor    %eax,%eax
  lea    D21(%rip),%rdi
  call   <getenv@plt>
  test   %eax,%eax
  jne    L166
  lea    D33(%rip),%rdi
  call   <chdir@plt>
  jmp    L79
  nopl   0x0(%rax,%rax,1)
L40:
  mov    0x8(%r12),%rdi
  test   %rdi,%rdi
  jne    L42
L132:
  add    $0x8,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax,%rax,1)
L166:
  movslq %eax,%rdi
  xor    %eax,%eax
  call   <chdir@plt>
  jmp    L79
L42:
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  jmp    11b0 <atoi@plt>
L109:
  mov    (%r12),%rdi
  mov    %r12,%rsi
  call   <execvp@plt>
  lea    D55(%rip),%rsi
  mov    $0x2,%edi
  xor    %eax,%eax
  call   <writestr@plt>
  mov    (%r12),%rsi
  mov    $0x2,%edi
  xor    %eax,%eax
  call   <writestr@plt>
  mov    $0x2,%edi
  lea    D11(%rip),%rsi
  xor    %eax,%eax
  call   <writestr@plt>
  mov    $0xff,%edi
  call   <_exit@plt>
```

tool_calls: name: read_data
arguments: data_label: D38
type: string
name: read_data
arguments: data_label: D67
type: string
name: read_data
arguments: data_label: D63
type: string
name: read_data
arguments: data_label: D21
type: string
name: read_data
arguments: data_label: D33
type: string
name: read_data
arguments: data_label: D55
type: string
name: read_data
arguments: data_label: D11
type: string

tool: D38: exit

tool: D67: $ 

tool: D63: sh: Syntax error


tool: D21: HOME

tool: D33: /

tool: D55: sh: 

tool: D11: : Not found


assistant: ```c
int sh(int f, int interactive) {
  char *line, **newargv, *tmpstr;
  for (;;) {
    if (interactive)
      writestr(1, "$ ");
    if ((line = readline(f)) == 0)
      return 0;
    if ((newargv = tokenize(line, strlen(line))) == 0)
      writestr(2, "sh: Syntax error\n");
    else if (*newargv != 0) {
      if (!strcmp(newargv[0], "exit")) {
        if (newargv[1] == 0)
          return 0;
        else
          return atoi(newargv[1]);
      } else if (!strcmp(newargv[0], "cd")) {
        if (newargv[1] == 0) {
          if ((tmpstr = getenv("HOME")) == 0)
            chdir("/");
          else
            chdir(tmpstr);
        } else
          chdir(newargv[1]);
      } else {
        if (fork())
          wait(0);
        else {
          execvp(newargv[0], newargv);
          writestr(2, "sh: ");
          writestr(2, newargv[0]);
          writestr(2, ": Not found\n");
          _exit(255);
        }
      }
    }
    free(line);
    line = 0;
    free(newargv);
    newargv = 0;
  }
  return 0;
}
```