Ладно, переходим к исходному коду!
Программа
util-linux
пользователя login
уже занята к моменту появления приглашения для входа в систему. Начнем там , точнее в файле login-utils/login.c
.
Теперь login
отвечает за подсказку login
, поскольку она генерируется вloginpam_get_prompt
и регистрируется в PAM вinit_loginpam
. Затем функцияloginpam_auth
вступает во владение, и управление переходит к функцииpam_authenticate
PAM. Это означает, что login
просто определяет подсказку для имени пользователя и все.
Для PAM тогда :то, что нас интересует, явно происходит вpam_authenticate
:
The pam_authenticate function is used to authenticate the user. The user is required to provide an authentication token depending upon the authentication service, usually this is a password, but could also be a finger print.
Теперь теневая -аутентификация (/etc/passwd
,/etc/shadow
)обрабатывается модулем pam_unix
. Мой дистрибутив (Arch )предоставляет PAM через пакет pam
, что означает, что наше путешествие продолжается к linux -pam.org и его исходному коду .modules/pam_unix/pam_unix_auth.c
кажется хорошим местом для начала. Модули PAM предоставляют свой механизм аутентификации через функцию pam_sm_authenticate
, которую мы находим здесь . Пароль (или «токен аутентификации», см. выше ), извлекается с помощью вызова функции PAM pam_get_authtok
. Он объявлен в заголовочном файле security/pam_ext.h
, так что мы идем дальше.
extern int PAM_NONNULL((1,3))
pam_get_authtok (pam_handle_t *pamh,
int item,
const char **authtok,
const char *prompt);
В этих рассуждениях нет ничего многообещающего, но хорошо... Давайте посмотрим определение . pam_unix
передал NULL
вместо аргумента prompt
и PAM_AUTHTOK
вместо item
, так что мы получаем здесь . Теперь этот жестко закодированный PAM_PROMPT_ECHO_OFF
, переданный pam_prompt
, просто не выглядит хорошо для меня...
retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], "%s", PROMPT);
Кстати, пароль PROMPT
также жестко запрограммирован(здесь ), так что моя мечта о более экзотическом запросе пароля исчезает... Впрочем, давайте перейдем к функции pam_prompt
. Фактическое приглашение происходит здесь , где PAM вызывает функцию диалога, выбранную несколькими строками выше . Беглый взгляд на функции pam_get_item
иpam_set_item
знакомит нас со структурой pam_conv
, определенной здесь .
Теперь найти информацию о функции диалога PAM по умолчанию было намного сложнее, чем следовало бы (Я думаю ). Куда бы я ни посмотрел, структура оставалась неинициализированной и pam_unix
, похоже, не определяет свою собственную. Однако мне удалось найти общую функцию misc_conv
, которая передает PAM_PROMPT_ECHO_OFF
наread_string
и... здесь , где PAM деактивирует входную обратную связь.
Заключение:отсутствие обратной связи по паролю жестко запрограммировано. Очень жаль. Немного покопавшись, я нашел эту проблему на GitHub и эту ветку Arch BBS . Судя по всему, эта функция была доступна еще тогда, когда PAM не был стандартом для аутентификации. Я предполагаю, что имеет смысл не реализовывать это снова -безопасность и все -, но вы знаете, вариант был бы хорош.
В общем, я только что заказал себе новую клавиатуру.
Поскольку в вашем теге указано bash
, вы можете использовать опцию globstar
:
shopt -s globstar
for d in **/; do if [[ -f "$d/my_suites.cfg" ]]; then cd "$d"; make; cd -; fi; done
Это будет перебирать все каталоги и подкаталоги -текущего каталога, проверять, существует ли файл my_suites.cfg
, и если да, переходить в этот каталог, вызывать make
и возвращаться в исходный каталог..
Вы можете использовать find
для выполнения команды (пример :pwd )с рабочим каталогом, в котором найден именованный файл:
find /path/to/repository -type f -name my_suites.cfg -execdir pwd \;
/path/to/repository также может быть относительным путем (даже ".")
Итак, чтобы обобщить вопрос :Вы хотите запустить команду bash для каждого файла которые имеют конкретное имя, по одному.
Предполагая, что вы готовы использовать существующие инструменты, а не писать все с нуля самостоятельно, вот несколько идей:
Если не имеет значения, что самые новые файлы еще не распознаны:
$ mlocate --basename --regex "^my_suites.cfg$" \
| xargs dirname \
| xargs -d '\n' <command-to-run-on-the-file>
В противном случае, если эффективность не так важна, (предполагая, что мы ищем рекурсивно только в домашнем каталоге(~
):
$ find ~ -name "my_suites.cfg" -type f \
| xargs dirname \
| xargs -d '\n' <command-to-run-on-the-file>
Если искомые файлы разбросаны по всей системе, должен заботиться об эффективности.
С некоторыми недостатками
$ mlocate --basename --regex "^my_suites.cfg$"
mlocate
ищет пути к файлам в базе данных, которая обновляется один раз в день для большинство дистрибутивов. Таким образом, он может не распознать недавно созданные или недавно переехал файлы. Но поскольку он просматривает базу данных вместо того, чтобы просматривать сама файловая система, ее поиск очень эффективен. --basename
указывает, что мы ищем прямой название файл, не включая путь/каталоги к нему. --regex
разрешает использование регулярных выражений в поиск шаблон. (^
ожидает, что строка начнется здесь, а $
ожидает строка, чтобы закончить там.)$ find / -name "my_suites.cfg" -type f
find
просматривает практически каждую папку, которую может найти, и перечисляет каждый файл с именем _suites.cfg. Из-за этого многие чтение -операций, которые он должен выполнить, тем больше папок он ищет тем медленнее он становится. -name
указывает, что мой _suites.cfg — это имя файл, вместо т.е. папки, в которой находится искомый нами файл.-type
указывает, что мы ищем файл , а не для каталог, символическая ссылка, сокет или что-то в этом роде. ... вот что значит xargs
для
$ echo "some simple example" | xargs mkdir
$ # now there are three directories, named by the echoed words
$ ls
example simple some
$ echo "hello world" | xargs -d ' ' -I % echo 'Print a word: %'
Print a word: hello
Print a word: world
-d
опция :указывает, какой символ отделяет аргументы от каждого другое (здесь :пробел ). -I
опция :Все вхождения данного символа(%
в этом примере )будет заменен аргументом, пришедшим из канала (до|
)Вот что происходит в приведенном выше примере:
echo
выводит «hello world» на стандартный вывод (stdout
). |
)передает это значение ("hello world" )следующей команде: который оказывается xargs
. xargs
ищет вхождения разделителя в аргументе и расколы аргумент, в котором он находит разделитель. xargs
перебирает только что созданные аргументы и запускает команду со значением аргумента вместо%