summary refs log tree commit diff stats
path: root/ranger/api/commands.py
diff options
context:
space:
mode:
Diffstat (limited to 'ranger/api/commands.py')
-rw-r--r--ranger/api/commands.py2
1 files changed, 1 insertions, 1 deletions
diff --git a/ranger/api/commands.py b/ranger/api/commands.py
index 56fc94a3..f5011232 100644
--- a/ranger/api/commands.py
+++ b/ranger/api/commands.py
@@ -389,7 +389,7 @@ class FunctionCommand(Command):
         args, keywords = list(), dict()
         for arg in self.args[1:]:
             equal_sign = arg.find("=")
-            value = arg if (equal_sign is -1) else arg[equal_sign + 1:]
+            value = arg if equal_sign == -1 else arg[equal_sign + 1:]
             try:
                 value = int(value)
             except ValueError:
href='#n100'>100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
:(before "End Initialize Op Names")
put_new(Name, "cd", "software interrupt (int)");

:(before "End Single-Byte Opcodes")
case 0xcd: {  // int imm8 (software interrupt)
  trace(Callstack_depth+1, "run") << "syscall" << end();
  uint8_t code = next();
  if (code != 0x80) {
    raise << "Unimplemented interrupt code " << HEXBYTE << code << '\n' << end();
    raise << "  Only `int 80h` supported for now.\n" << end();
    break;
  }
  process_int80();
  break;
}

:(code)
void process_int80() {
  switch (Reg[EAX].u) {
  case 1:
    exit(/*exit code*/Reg[EBX].u);
    break;
  case 3:
    trace(Callstack_depth+1, "run") << "read: " << Reg[EBX].u << ' ' << Reg[ECX].u << ' ' << Reg[EDX].u << end();
    Reg[EAX].i = read(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u);
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "read: " << strerror(errno) << '\n' << end();
    break;
  case 4:
    trace(Callstack_depth+1, "run") << "write: " << Reg[EBX].u << ' ' << Reg[ECX].u << ' ' << Reg[EDX].u << end();
    trace(Callstack_depth+1, "run") << Reg[ECX].u << " => " << mem_addr_string(Reg[ECX].u, Reg[EDX].u) << end();
    Reg[EAX].i = write(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u);
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "write: " << strerror(errno) << '\n' << end();
    break;
  case 5: {
    check_flags(ECX);
    check_mode(EDX);
    trace(Callstack_depth+1, "run") << "open: " << Reg[EBX].u << ' ' << Reg[ECX].u << end();
    trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end();
    Reg[EAX].i = open(/*filename*/mem_addr_kernel_string(Reg[EBX].u), /*flags*/Reg[ECX].u, /*mode*/0640);
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "open: " << strerror(errno) << '\n' << end();
    break;
  }
  case 6:
    trace(Callstack_depth+1, "run") << "close: " << Reg[EBX].u << end();
    Reg[EAX].i = close(/*file descriptor*/Reg[EBX].u);
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "close: " << strerror(errno) << '\n' << end();
    break;
  case 8:
    check_mode(ECX);
    trace(Callstack_depth+1, "run") << "creat: " << Reg[EBX].u << end();
    trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end();
    Reg[EAX].i = creat(/*filename*/mem_addr_kernel_string(Reg[EBX].u), /*mode*/0640);
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "creat: " << strerror(errno) << '\n' << end();
    break;
  case 10:
    trace(Callstack_depth+1, "run") << "unlink: " << Reg[EBX].u << end();
    trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end();
    Reg[EAX].i = unlink(/*filename*/mem_addr_kernel_string(Reg[EBX].u));
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "unlink: " << strerror(errno) << '\n' << end();
    break;
  case 38:
    trace(Callstack_depth+1, "run") << "rename: " << Reg[EBX].u << " -> " << Reg[ECX].u << end();
    trace(Callstack_depth+1, "run") << Reg[EBX].u << " => " << mem_addr_kernel_string(Reg[EBX].u) << end();
    trace(Callstack_depth+1, "run") << Reg[ECX].u << " => " << mem_addr_kernel_string(Reg[ECX].u) << end();
    Reg[EAX].i = rename(/*old filename*/mem_addr_kernel_string(Reg[EBX].u), /*new filename*/mem_addr_kernel_string(Reg[ECX].u));
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].i << end();
    if (Reg[EAX].i == -1) raise << "rename: " << strerror(errno) << '\n' << end();
    break;
  case 90:  // mmap: allocate memory outside existing segment allocations
    trace(Callstack_depth+1, "run") << "mmap: allocate new segment" << end();
    // Ignore most arguments for now: address hint, protection flags, sharing flags, fd, offset.
    // We only support anonymous maps.
    Reg[EAX].u = new_segment(/*length*/read_mem_u32(Reg[EBX].u+0x4));
    trace(Callstack_depth+1, "run") << "result: " << Reg[EAX].u << end();
    break;
  case 0xa2:  // nanosleep
    cerr << "not sleeping\n";
    break;
  default:
    raise << HEXWORD << EIP << ": unimplemented syscall " << Reg[EAX].u << '\n' << end();
  }
}

// SubX is oblivious to file permissions, directories, symbolic links, terminals, and much else besides.
// Also ignoring any concurrency considerations for now.
void check_flags(int reg) {
  uint32_t flags = Reg[reg].u;
  if (flags != ((flags & O_RDONLY) | (flags & O_WRONLY))) {
    cerr << HEXWORD << EIP << ": most POSIX flags to the open() syscall are not supported. Just O_RDONLY and O_WRONLY for now. Zero concurrent access support.\n";
    exit(1);
  }
  if ((flags & O_RDONLY) && (flags & O_WRONLY)) {
    cerr << HEXWORD << EIP << ": can't open a file for both reading and writing at once. See http://man7.org/linux/man-pages/man2/open.2.html.\n";
    exit(1);
  }
}

void check_mode(int reg) {
  if (Reg[reg].u != 0600) {
    cerr << HEXWORD << EIP << ": SubX is oblivious to file permissions; register " << reg << " must be 0x180.\n";
    exit(1);
  }
}

:(before "End Globals")
// Very primitive/fixed/insecure mmap segments for now.
uint32_t Segments_allocated_above = END_HEAP;
:(code)
// always allocate multiples of the segment size
uint32_t new_segment(uint32_t length) {
  assert(length > 0);
  uint32_t result = (Segments_allocated_above - length) & 0xff000000;  // same number of zeroes as SEGMENT_ALIGNMENT
  if (result <= START_HEAP) {
    raise << "Allocated too many segments; the VM ran out of memory. "
          << "Maybe SEGMENT_ALIGNMENT can be smaller?\n" << die();
  }
  Mem.push_back(vma(result, result+length));
  Segments_allocated_above = result;
  return result;
}