2014-02-05 4 views
0

Im пытается получить мою программу для запуска команды оболочки из-за использования exelp(). Пользователь в основном вводит команду оболочки, которая сохраняется и затем выполняется exelp() в новой оболочке.Запуск команды оболочки с execlp() из строки

Скажем, пользователь вводит «ls -l/bin/??», который, в свою очередь, фиксируется переменной command[]. Как я могу заставить эту текстовую строку выполнять в оболочке envionment.

Ближайший я пришел к пониманию того, как сделать это было бы, делая execlp("/bin/sh", "-c", command, (char *)NULL);, где /bin/sh запускает мини-оболочку, -c позволяет оболочку брать строки, а второй последний аргумент просто строка захваченной ранее. Я знаю, что system() является вариантом здесь, но я хочу сделать это с помощью execlp для образовательных целей.

Что мне здесь не хватает? Заранее спасибо.

+1

В 'exec' нет вызова, который принимает одну строку аргументов. Вашими параметрами являются либо список строк, либо массив строк. Это означает, что перед использованием одного из вызовов 'exec' вам необходимо проанализировать свою входную строку в отдельные аргументы. Вы сделали это вручную. Теперь вам нужно сделать это программно. – Duck

+1

Вы можете использовать 'execlp()' только в очень ограниченном количестве обстоятельств; вы должны знать количество аргументов во время компиляции. Вместо этого вы обычно используете 'execvp()'. –

ответ

-1

Вы ставите const char** вместо const char * в качестве аргумента tird

попробовать execlp("/bin/sh", "-c", "ls", "-l", "/bin/", 0) или создать другой символ ** с «-с» в качестве первого аргумента, а затем использовать execv

Я предполагаю, что это компиляция поскольку два аргумента указатель, но они имеют неправильный тип

EDIT

, когда вы вызываете execlp, как и вы. , как вы говорите, команда является const char[], но в определении нужно поставить только const char* это как если вы вызываете функцию, как, что

execlp(const char*, const char*, const char **, char*) //wrong obviously 

поэтому у вас есть два решения. Первый с помощью бен/ш -с это в Concat всех аргументов и передать его функции имеют

int main(int argc, char **av) 
{ 
    char **args; 
    int i; 
    char *cmd; 
    size_t size; 

    args = malloc(sizeof(char*) * (4)); 
    args[0] = "sh"; 
    args[1] = "-c"; 
    i = 1; 
    size = 0; 
    cmd = malloc(1); 
    *cmd = '\0'; 
    while (i < argc) 
    { 
     cmd = realloc(cmd, strlen(cmd) + 1 + strlen(av[i])); 
     strcat(&(cmd[size]), av[i]); 
     size += strlen(cmd); 
     strcat(&(cmd[size]), " "); 
     size++; 
     i++; 
    } 
    args[2] = cmd; 
    execvp("/bin/sh", args); 
} 

Но это не очень чистый

Лучший способ (и тем более логичный для меня) Я думаю, что это найти адрес бинарного так в вашем случае/bin/LS, а затем передать его с помощью execvp

что-то вроде:

char *get_binary_addr(const char* fct) 
{ 
    return "/bin/ls"; //ofc you will parse your /bin to find binary addr 
} 

int main(int argc, char **av) 
{ 
    char **args; 

    args = malloc(sizeof(char*) * argc); 
    memcpy(&(args[0]), &(av[1]), argc * sizeof(char*)); 
    execvp(get_binary_addr(av[0]), args); 
} 
+0

Спасибо @Alexis. Что вы имеете в виду, я использую 'const char **' в третьем аргументе? Вы имеете в виду указатель NULL? Кроме того, я явно должен запускать команду из одной строки, содержащей всю команду. Следовательно, «ls», «-l» ... не вариант для меня. –

+0

Я отредактировал свой ответ – Alexis

+0

Первый фрагмент пропускает установку 'args [3] = NULL;'. – alk

0

Может быть, вы спрашивают, как расширить внутри вашей программы C слово оболочки в подпоследовательность аргумента. См glob(7)

Тогда рассмотрим glob(3) и wordexp(3)

Вы должны понимать, что, когда вы набираете ls -l /bin/?? это обязанность оболочечных расширить ??; программа /bin/ls равна execve(2) -ed с результатом расширение, сделанное оболочкой ...

В качестве альтернативы вы можете оставить это для оболочки /bin/sh -c, начатой ​​system(3) или popen(3) функциями. Если вы передадите этим функциям некоторые пользовательские входы, остерегайтесь code injection и заказывайте соответствующим образом любой пользовательский ввод. Представьте, что вы запустили строку, состоящую из ls -l и некоторого ввода пользователем; если злоумышленник дает a; rm -rf $HOME в качестве имени файла, вам будет жаль, если вы его не процитируете (потому что без каких-либо мер предосторожности ваша программа будет строить командную строку ls -l a; rm -rf $HOME, тогда эта строка будет передаваться в system или popen, а затем произойдет катастрофа).

Смежные вопросы