2016-06-26 2 views
3

Мне нужно получить домашнюю папку пользователя. На данный момент я использую этотРасширение тильды без eval

home=$(eval echo ~$user) 

Содержание $user обеспечивается вызывающей, поэтому не доверяет значение. Возможно ли использование здесь eval? Если да (возможно), как решить это без него?

+0

что-то вроде '$ (cd ~; pwd)' может быть? – n0rd

+1

@ n0rd - Я думаю, что OP означает, что им нужно получить домашнюю папку данного имени пользователя, имя пользователя, указанное из ненадежного источника. –

+1

'eval' опасен на * неутвержденный * вход; вы можете убедиться, что '$ user' содержит только допустимое имя пользователя с чем-то вроде [[$ user = ~ [a-zA-Z] [a-zA-Z0-9_]]] && home = $ (eval echo ~ $ пользователю) '. (Я точно не помню, что представляет собой действительное имя пользователя, но это что-то вроде действительного идентификатора.) – chepner

ответ

4

В системах, вы можете использовать getent(1):

$ getent passwd "$username" | cut -d: -f 6 
/path/to/user/home 

Убедитесь, чтобы проверить пустые результаты, хотя.

+0

Прохладный, я пойду с этим, спасибо. Работает на моем Linux-боксе. Остается посмотреть, работает ли он также в cygwin. – Paladin

1

Расширение Тильды происходит очень рано в процессе синтаксического анализа, и нет никаких способов добиться того, чего вы хотите без нескольких оценок. Следовательно, eval- решение. Самый безопасный способ добиться того, что вы хотите:

eval "$(printf "home=~%q" "$user")" 

Благодаря модификатором %q, расширение $user будет полностью цитировал, так что нет никакой опасности здесь (не изменить строку, хотя, вы, конечно, ввести некоторые дыры в безопасности).

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

if [[ ! -d $home ]]; then 
    echo >&2 "Couldn't find home dir for user $user" 
    exit 1 
fi 

Также рассмотрим случай, когда user пусто: в этом случае, home будет домашним каталогом пользователя, запускающего скрипт. Хочешь ли ты этого поведения или нет, зависит от тебя.

Существует еще один момент для рассмотрения: когда user содержит косые черты: хотите ли вы эту функцию или нет, зависит от вас.

Теперь, в зависимости от того, каких функций вы хотите иметь, это могло бы быть лучше, чтобы подтвердить расширение $user против какой-то определенной схемы один раз для всех, например,

if [[ $user != [a-z]*([-a-z0-9_]) ]]; then 
    echo >&2 'Provided user doesn't match valid pattern' 
    exit 1 
fi 

И получается, что с этой проверкой, ваше решение безопасно.


Примеры:

Случай, когда все работает хорошо:

$ user=gniourf 
$ eval "$(printf "home=~%q" "$user")" 
$ declare -p home 
declare -- home="/home/gniourf" 

Случай, который может быть опасным с кодом (с кодом, ls будет выполнен, но не здесь) :

$ user='; ls >&2' 
$ eval "$(printf "home=~%q" "$user")" 
$ declare -p home 
declare -- home="~; ls >&2" 
Смежные вопросы