выполнить внешнюю программу в lua без userinput в качестве аргументов в lua - PullRequest
0 голосов
/ 11 ноября 2018

Я хочу выполнить внешнюю программу в lua.Обычно это можно сделать с помощью

os.execute("run '"..arg0.."' 'arg1' arg2")

. Проблема с этим подходом заключается в том, что если я хочу передать пользовательский ввод в виде строки во внешнюю программу, пользовательский ввод может быть '; evil 'h4ck teh system' ', а приведенный выше скрипт будет выполняться следующим образом:this:

/bin/bash -c "run ''; evil 'h4ck teh system' '' 'arg1' arg2"

Другая проблема возникает, когда у меня есть '$var' в качестве аргумента, и оболочка заменяет его своей переменной среды.В моем конкретном случае у меня есть что-то вроде [[program 'set title "$My Title$"']] - поэтому вложенные строки - и program анализирует "$My Title$" (с escape-последовательностями) иначе, чем '$My Title$' (как есть).Поскольку я хочу установить для него заголовок, лучший способ - аргументы, подобные этому: 'My Title'.Но теперь команда должна быть:

os.execute([[run "set title '$My Title$'"]])

Но теперь - как я уже сказал - $My будет заменен пустой строкой, потому что среда не знает никакой переменной с именем $My и потому, что,Я никогда не хотел, чтобы его заменили.

Поэтому я ищу обычный подход с

execv("run", {"set title '"..arg0.."'", arg1, arg2})

1 Ответ

0 голосов
/ 11 ноября 2018
local safe_unquoted = "^[-~_/.%w%%+,:@^]*$"
local function q(text, expand)   -- quoting under *nix shells
   -- "expand"
   --    false/nil: $var and `cmd` must NOT be expanded (use single quotes)
   --    true:      $var and `cmd` must be expanded (use double quotes)
   if text == "" then
      text = '""'
   elseif not text:match(safe_unquoted) then
      if expand then
         text = '"'..text:gsub('["\\]', '\\%0')..'"'
      else
         local new_text = {}
         for s in (text.."'"):gmatch"(.-)'" do
            new_text[#new_text + 1] = s:match(safe_unquoted) or "'"..s.."'"
         end
         text = table.concat(new_text, "\\'")
      end
   end
   return text
end

function execute_commands(...)
   local all_commands = {}
   for k, command in ipairs{...} do
      for j = 1, #command do
         if not command[j]:match"^[-~_%w/%.]+$" then
            command[j] = q(command[j], command.expand)
         end
      end
      all_commands[k] = table.concat(command, " ") -- space is arguments delimiter
   end
   all_commands = table.concat(all_commands, ";")  -- semicolon is commands delimiter
   return os.execute("/bin/bash -c "..q(all_commands))
end

Примеры использования:

-- Usage example #1:
execute_commands(
   {"your/program", "arg 1", "$arg2", "arg-3", "~/arg4.txt"},
   {expand=true, "echo", "Your program finished with exit code $?"},
   {"ls", "-l"}
)
-- The following command will be executed:
-- /bin/bash -c 'your/program '\''arg 1'\'' '\''$arg2'\'' arg-3 ~/arg4.txt;echo "Your program finished with exit code $?";ls -l'

$arg2 НЕ будет расширяться до значения из-за одинарных кавычек, как вам требуется.
К сожалению, "Your program finished with exit code $?" тоже НЕ будет расширен (если вы явно не установите expand=true).

-- Usage example #2:
execute_commands{"run", "set title '$My Title$'", "arg1", "arg2"}
-- the generated command is not trivial, but it does exactly what you need :-)
-- /bin/bash -c 'run '\''set title '\''\'\'\''$My Title$'\''\'\'' arg1 arg2'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...