LINUX.ORG.RU

Как кроссплатформенно получить название командной оболочки ОС?

 ,


0

1

Есть ли како-нибудь надёжный переносимый способ на C++ получить название командной оболочки операционной системы, в т.ч. и винды без лишних фреймворков кроме Qt?

★★★
Ответ на: комментарий от NAY_GIGGER

Командная оболочка как процесс или просто используемая в системе?

Нужно её выполнить.

normann ★★★
() автор топика
Ответ на: комментарий от no-such-file

Что бы выполнить команду в которой перечислены разные программы через пайпы, такую команду может переварить может только оболочка, как я понимаю.

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

Да. Но строка с командой приходит уже готовая из внешнего кода. Я могу разбить строку по символам пайпов, и выполнить отдельно через QProcess::setStandardOutputProcess(), но парсить строку это такое себе, а внешний код я трогать не хочу, но возможно придётся, если не найдётся более быстрого решения. Пока что это основной кандидат, из тех, что приходит мне в голову.

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

Почему не просто int system(const char *command)?

Нужно получить итоговый стандартный вывод. В текущей реализации, которая мне досталась, исполняется через system, с приставкой к строке перенаправления в файл, а потом читается из него.

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

Я бы попробовал первым делом найти embeddable shell в виде библиотеки (желательно статичной). А если нет то просто сделать список всевозможных шеллов и их возможные местоположения и потом использовать первый найденный.

NAY_GIGGER
()

Сделай возможность указать шелл через конфиг руками.

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

В винде же нет никаких пайпов, что ты там собрался выполнять?

А так, вот тебе варианты:

  • Используй /bin/sh, оно просто везде есть. Кроме венды, конечно.
  • Достань строку с /bin/sh из стандартной библиотеки, потому что system выполняет её, и она хранится где-то в константе. Не знаю насколько она публичная и стандартизированная, но вот например что есть под фряхой:
    // это из исходника system() (lib/libc/stdlib/system.c)
    execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
    
    % grep -R _PATH_BSHELL /usr/include 
    /usr/include/paths.h:#define	_PATH_BSHELL	"/bin/sh"
    /usr/include/paths.h:#undef	_PATH_BSHELL
    /usr/include/paths.h:#define	_PATH_BSHELL	"/rescue/sh"
    
  • Правильный вариант - не используй шелл, собери нужный пайплайн руками. Насоздавай нужное число pipe, нужное число раз форкнись, в детях настрой сигналы, переопередели дескрипторы на пайпы и exec’ни нужные процессы. Это именно то что делает шелл создавая пайплайн.
slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Уточнение из стандарта:

Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH , ensuring that the returned pathname is an absolute pathname and not a shell built-in.

Но я бы намеренно не поддерживал системы где нет /bin/sh.

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

Есть даже в cmd.exe

C:\>dir | findstr Program
20.10.2021  23:42    <DIR>          Program Files
20.10.2021  23:44    <DIR>          Program Files (x86)

Ну а про PowerShell и говорить не приходится

Begemoth ★★★★★
()
Последнее исправление: Begemoth (всего исправлений: 1)

Эталон ненужности. Но если так охота - просто вынеси шаблон запуска команды в конфиг

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

Но я бы намеренно не поддерживал системы где нет /bin/sh

Оно всегда есть на freebsd/bsd без дополнительных установок?

normann ★★★
() автор топика
Последнее исправление: normann (всего исправлений: 1)
Ответ на: комментарий от normann

Что бы выполнить команду в которой перечислены разные программы через пайпы, такую команду может переварить может только оболочка, как я понимаю.

  1. Вынеси команду в отдельный скриптовый файл.
  2. Скопируй его и сделай две разные версии для POSIX shell и cmd.exe
  3. Вызови нужный скрипт через /bin/sh под ифдефом для юниксов и cmd /k под ифдефом для виндов, изменяемые параметры передавай через аргументы

Что-то более переносимое ты вряд ли придумаешь. Толко если вообще отказаться от пайпов и делать закат солнца вручную, как уже предлагали выше.

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

Ты издеваешься? Да даже MS-DOS 3.3 в конце 80-x умел в пайпы и перенаправление.

DIR | SORT
DIR > FILES

Понятно, что реализовано это было скорее всего через временные файлы, но тем не менее. Что уж говорить о винде.

bigbit ★★★★★
()
Последнее исправление: bigbit (всего исправлений: 1)
Ответ на: комментарий от slovazap

Правильный вариант - не используй шелл, собери нужный пайплайн руками.

Ну не знаю, не знаю. Независимость от шелла это хорошо, но с другой стороны придется заново реализовывать часть функционала шелла. И парсер командной строки, и механизм соединения запускаемых программ пайпами. Ничего невозможного конечно нет, но это еще нужно будет сделать.

Вычислить шелл, запустить с параметром -c и забрать его stdout проще.

Как-то так например:

boost::process::ipstream is; //reading pipe-stream
boost::process::child c("/bin/sh", "-c", cmd, boost::process::std_out > is);

std::vector<std::string> data;
std::string line;

while (c.running() && std::getline(is, line) && !line.empty()) {
    data.push_back(line);
}

c.wait();

Для винды соответственно сделать поправку на путь к шеллу.

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

И парсер командной строки

Никакой парсер, конечно же, реализовывать не надо.

механизм соединения запускаемых программ пайпами

Там нечего реализовывать. Запуска пайплайна ничем не отличается от обычного запуска одного дочернего процесса.

slovazap ★★★★★
()

В общем послушал вас и сделал времянку через /bin/sh -с, на овфтоп забил пока (не срочно). Дальше, когда будет время переделаю код, который передаёт мне строку с командой с пайпами, будет передавать список строк для каждого процесса, и (как и посоветовал slovazap) выполню их через отдельные процессы, организуя связь между ними самостоятельно, только сделаю это не при помощи стандартной библиотеки, а через Qt. Спасибо, парни, за отзывчивость.

normann ★★★
() автор топика
Последнее исправление: normann (всего исправлений: 2)
Ответ на: комментарий от normann

Что бы выполнить команду в которой перечислены разные программы через пайпы

Нужно вызывать не абы какую оболочку, а ту, которая эту команду гарантированно переварит. И это я ещё не предлагал этот мрак выкинуть и не передавать произвольный код строкой.

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