Удалить аргумент из $@, если это опция

at least one uses spaces for delimiters

Неверно.

Если вы посмотрите в конец псевдофайла -в FreeBSD/TrueOS, где вы можете столкнуться с точно таким же поведением с Chromium, вы найдете . Это равно и #x2400; -прекращено. Это все один единственный аргумент .

Chromium перезаписывает свои аргументы после fork(), чтобы дать вам что-то интересное для просмотра в выводе ps. Он использует библиотечную функцию setproctitle(). Это часть библиотек BSD C. Он не является частью библиотеки GNU C. На платформах GNU C Chromium использует и setproctitle()собственный , который напрямую перезаписывает данные argv.

setproctitle()на самом деле не является подходящим инструментом для этой работы, потому что он не позволяет устанавливать более одной строки аргументов. Он устанавливает отформатированное «заголовок» в качестве 0-го аргумента и устанавливает количество аргументов равным 1. Все сортируется через библиотечную функцию как один единственный аргумент.

Это не единственная проблема с setproctitle(). Версия библиотеки C для FreeBSD/OpenBSD/NetBSD также имеет произвольное ограничение в 2 КБ, унаследованное непосредственно от старой программы BSD sendmail(, из которой библиотечная функция была первоначально удалена в случае FreeBSD ), что слишком мало. для чего Chromium часто устанавливает командные строки. И собственная версия библиотеки Chromium, и версия библиотеки FreeBSD/OpenBSD/NetBSD C имеют дополнительную функциональность, поскольку строка формата является нулевым указателем, который Chromium не использует (, но, по иронии судьбы, должен иметь дело с собственной реализацией setproctitle(). тем не менее ).

Можно сделать намного лучше, используя меньше кода.Базовый системный вызов в FreeBSD/TrueOS, который библиотечная функция вызывает для выполнения работы после создания данных аргумента, — это функция sysctl(), принимающая CTL_KERN, KERN_PROC, KERN_PROC_ARGSи идентификатор процесса в качестве адреса. Этот может принимать несколько & #x2400; -завершенные строки. Я написал довольно простую функцию setprocargv()для своих наборов инструментов, которая использует это.

extern
void
setprocargv (
    size_t argc,
    const char * argv[]
) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
    std::string s;
    for (size_t c(0); c < argc; ++c) {
        if (!argv[c]) break;
        s += argv[c];
        s += '\0';
    }
    const int oid[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, getpid() };
    sysctl(oid, sizeof oid/sizeof *oid, 0, 0, s.data(), s.length());
#elif defined(__OpenBSD__) …

(OpenBSD/NetBSD работает по-старому, как FreeBSD/TrueOS, со структурой ps_stringsв памяти приложения, но по-прежнему sysctl()является базовым системным вызовом, используемым для поиска местоположения этой структуры..)

% /package/admin/nosh/command/exec foreground pause \; true &
[1] 30318
% hexdump -C /proc/30318/cmdline
00000000  66 6f 72 65 67 72 6f 75  6e 64 00 70 61 75 73 65  |foreground.pause|
00000010  00 3b 00 74 72 75 65 00                           |.;.true.|
00000018
% hexdump -C /proc/30319/cmdline
00000000  70 61 75 73 65 00                                 |pause.|
00000006
%

Поскольку setproctitle()не подходит для этой работы, Chromium берет новые argvчлены и создает единый long & #x2420; -строка из них с разделителями, которая должна быть передана как один аргумент в setproctitle().

  for (size_t i = 1; i < command_line->argv().size(); ++i) {
    if (!title.empty())
      title += " ";
    title += command_line->argv()[i];
  }
  // Disable prepending argv[0] with '-' if we prepended it ourselves above.
  setproctitle(have_argv0 ? "-%s" : "%s", title.c_str());

Как видите, сам Chromium уже имеет новый вектор аргументов в виде последовательности & #x2400; -завершенные строки. Он передает его через промежуточный библиотечный уровень, который требует, чтобы все они были сгруппированы в одну строку, где фактический уровень системного вызова, тем не менее, оперирует вектором аргументов & #x2400; -завершенные строки.

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

Возможно, вы могли бы убедить авторов Chromium принять что-то вроде setprocargv(). & #9786;

Дополнительная литература

  • Питер Вемм (1995 -12 -16 ).setproctitle. Руководство по функциям библиотеки FreeBSD . FreeBSD.
0
25.02.2020, 02:47
2 ответа

Если параметры, начинающиеся с -, никогда не принимают аргументы, достаточно просто использовать массивopts:

for a; do
   shift
   case $a in
   -*) opts+=("$a");;
   *) set -- "$@" "$a";;
   esac
done

(измените opts+=("$a")на opts="$opts$a ", если вы хотите, чтобы optsбыло строкой, что заставит фрагмент работать с любой стандартной оболочкой ).

2
28.04.2021, 23:22

В bash, ksh, zsh одно расширение очистит все аргументы, начинающиеся с-:

echo "${@##-*}"

Обратите внимание, что это не удаляет аргументы, а просто делает их нулевыми.

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

Простая петля предпочтительнее:

unset args opts;
for a; do
    if [[ $a == [-]* ]]; then
        opts+=("$a");
    else 
        args+=("$a");
    fi;
done;

printf '<%s> ' "${args[@]}"; echo;
printf '<%s> ' "${opts[@]}"; echo;
0
28.04.2021, 23:22

Теги

Похожие вопросы