LINUX.ORG.RU

как правильно кавычить строку?

 ,


1

1

Допустим, мне надо сделать такую не очень красивую вещь: моя программа на С принимает от юзера строку hostname и делает fork & exec вот такой команды: bash -c 'ping hostname'.

Проблема вот в чем: hostname может содержать какое-нибудь «127.0.0.1 && kill -9 100500», и надо ее shell-quote. Как это правильно сделать?

man bash говорит «A single quote may not occur between single quotes, even when preceded by a backslash.». То есть одинарные кавычки не сработают потому что юзер может послать кавычку. С двойными кавычками надо какие-то символы вроде $ эскейпить.

Расскажите плз как сделать так чтобы работало 100%?



Последнее исправление: Klymedy (всего исправлений: 1)
$ builtin printf "%q" "127.0.0.1 && rm -rf /\n"
127.0.0.1\ \&\&\ rm\ -rf\ /\\n
yekka
()
Ответ на: комментарий от nokachi

Но вообще хотелось бы узнать какой-то общий метод кавыченья (не знаю как перевести quoting).

1. всё засовываешь в 'одиночные кавычки'

2. сами одиночные кавычки меняешь на '"'"'

Оно работает, но если тебя кто-то спросит «кто тебе посоветовал засунуть bash скрипт в C программу и в продакшен?» пожалуйста, не ссылайся на меня.

emulek
()
Ответ на: комментарий от Deleted

Ещё можно использовать переменные окружения, если не хочется возиться с номерами параметров.

$ export FOO='127.0.0.1" && ls /'
$ bash -c 'ping "$FOO"'          
ping: unknown host 127.0.0.1" && ls /

NeXTSTEP ★★
()
Ответ на: комментарий от emulek

Покажешь пример, где это не работает?

~$ echo \'
'
~$ echo a\'a
a'a
~$ echo 'a'\''a'
a'a

Если ты сам ниасилил распарсить три склеенных токена, то это не значит, что шелл тоже не распарсит.

arturpub ★★
()
Ответ на: комментарий от arturpub

ну я откуда знал, что ты там добавлять будешь кавычки внутрь кавычек. Так — да, без разницы. Мой вариант красивее ИМХО (: Не люблю заборчики.

emulek
()
Ответ на: комментарий от anonymous

А вдруг команда изменится, переписывать весь код?

cat facepalm.diff

- exec("ping", "-c", "something");
+ exec("my_significant_other_ping", "--my-c", "my-something");

KennyMinigun ★★★★★
()
Ответ на: комментарий от nokachi

Допустим, мне надо сделать такую не очень красивую вещь: моя программа на С принимает от юзера строку hostname и делает fork & exec вот такой команды: bash -c 'ping hostname'.

интерпретатор запускаю не я а тот кому я это втроку передаю

Ну так зачем интерпретатор-то запускается? Не проще ли так (если не хочется лезть в сорцы пинга):

#include <unistd.h>
#include <sys/wait.h>

#include <cstdlib>
#include <cstring>
#include <cerrno>

#include <string>
#include <iostream>

bool ping(const std::string &hostname) {
    pid_t pid = fork();
    if (pid == -1) {
        std::cerr << "Fork failed: " << std::strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }

    if (pid) {
        int status;
        if (waitpid(pid, &status, 0) == -1) {
            std::cerr << "Waitpid failed: " << std::strerror(errno) << std::endl;
            exit(EXIT_FAILURE);
        }

        return WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS;
    } else {
        close(STDOUT_FILENO);
        if (execl("/bin/ping", "ping", "-c", "1", hostname.c_str(), NULL) == -1) {
            std::cerr << "Exec failed: " << std::strerror(errno) << std::endl;
            exit(EXIT_FAILURE);
        }

        // just to please the compiler
        return false;
    }
}

И вообще — толковый был совет про man popen

KennyMinigun ★★★★★
()
Ответ на: комментарий от KennyMinigun

Только стоило бы поменять exit(EXIT_FAILURE); на выброс исключений, не зря же тут С++

KennyMinigun ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.