3

В настоящее время я работаю в школе над самодельной оболочкой, поэтому мне сейчас любопытно, как устроены оболочки. Да, это может быть действительно захватывающим!

В любом случае, нам, очевидно, приходится иметь дело со случаем, когда наша оболочка будет запущена с пустым окружением, то есть командой «env -i». При использовании env -i переменная среды extern абсолютно пуста, поэтому нам нужно создать базовый PATH, PWD и все остальное.

Наша ссылка csh, потому что это легко и просто. Когда вы запускаете csh с помощью env -i, а затем выводите переменные, вот что вы можете увидеть:

$ env -i csh
% set
addsuffix
argv    ()
csubstnonl
cwd /Users/noesierra-velasquez
dirstack    /Users/noesierra-velasquez
echo_style  bsd
edit
gid 20
group   staff
history 100
killring    30
owd
path    (/usr/bin /bin)
prompt  %
prompt2 %R?
prompt3 CORRECT>%R (y|n|e|a)?
shell   /bin/tcsh
shlvl   1
status  0
tcsh    6.17.00
tty ttys001
uid 501
user    noesierra-velasquez
version tcsh 6.17.00 (Astron) 2009-07-10 (x86_64-apple-darwin) options         wide,nls,dl,al,kan,sm,rh,color,filec
% env
HOSTTYPE=intel-mac
VENDOR=apple
OSTYPE=darwin
MACHTYPE=x86_64
SHLVL=1
PWD=/Users/noesierra-velasquez
LOGNAME=noesierra-velasquez
USER=noesierra-velasquez
GROUP=staff
HOST=MacBook-Pro-de-Noe-Sierra-Velasquez.local
REMOTEHOST=

Итак, как вы можете видеть, HOME не установлен, и он кажется мне абсолютно нормальным. Если вы наберете cd , вы получите cd: No home directory. , Мы живем в нормальном мире.

Но здесь магия. Типа, внутри вашего пустого csh env -i zsh . Zsh загрузит. Теперь выведите все переменные env. (Примечание: это прекрасно работает, если вы набираете напрямую env -i zsh , даже из zsh, я делаю это здесь так, только чтобы быть уверенным, что нет хитрого трюка с zsh, вызывающим себя или что-то в этом роде)

% env -i zsh
$ env
HOME=/Users/noesierra-velasquez
LOGNAME=noesierra-velasquez
SHLVL=1
PWD=/Users/noesierra-velasquez
OLDPWD=/Users/noesierra-velasquez
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
_=/usr/bin/env

Вот Это Да ! Что случилось !? Кажется, у zsh есть способ вернуть $ HOME и $ OLDPWD из того, что мне кажется чистым небытием. (кстати, если кто-то не знает, я уверен, что он использует paths.h, чтобы вернуться на свой путь).

Очевидно, я знаю, что "чистое ничто" не является жизнеспособной возможностью, поэтому я спрашиваю вас, ребята: вы знаете, как zsh возвращает HOME и OLDPWD?

Спасибо за ваше терпение и хорошего дня! :)

2 ответа2

1
  1. В документации сказано следующее о переменной $HOME :

    HOME <S> Аргумент по умолчанию для команды cd. Это не устанавливается автоматически оболочкой в эмуляции sh, ksh или csh, но в любом случае она обычно присутствует в среде, и если она устанавливается, она имеет свое обычное специальное поведение.

    Я прочитал его наоборот, когда zsh вызывается сам по себе, он собирает информацию о homedir из управления пользователями системы. Этот (неполный) фрагмент (из Src/init.c) служит доказательством:

    /* Получить пароль и установить информацию для `USERNAME '*/if ((pswd = getpwuid (cached_uid))) {if (EMULATION (EMULATE_ZSH)) home = metafy (pswd -> pw_dir, -1, META_DUP); ...
    /* Попробуйте дешевый тест, чтобы увидеть, сможем ли мы инициализировать `PWD 'из` HOME'.
    В неродных эмуляциях HOME должен исходить из окружающей среды; нам не разрешено устанавливать это локально.
    */if (EMULATION (EMULATE_ZSH)) ptr = home ; иначе ptr = zgetenv ("ДОМ") ; ...

    Таким образом, без эмуляции (т.е., эмулировать zsh '') homedir определяется системным вызовом getpwuid . Только в противном случае используется окружение $HOME .

  2. Я не могу воспроизвести твою "магию" с помощью $PWD и $OLDPWD . Но, возможно, вам следует подумать о том, чтобы вызвать zsh как zsh -f , чтобы ни один пользователь (zsh не знал ваш homedir!) и общесистемные настройки get source'd. С помощью этой команды я получаю следующую среду в окне Debian:

    $ pwd/tmp $ env -i zsh -f jessie% env HOME =/home/user LOGNAME = user SHLVL = 1 PWD =/tmp OLDPWD =/tmp _ =/usr/bin/env jessie% 

    Итак, нет ничего удивительного в значениях $PWD и $OLDPWD . Исходный код, устанавливающий эти параметры, следует непосредственно приведенному выше коду:

    иначе if ((ptr = zgetenv ("PWD")) && (strlen (ptr) <PATH_MAX) && (ptr = metafy (ptr, -1, META_STATIC), ispwd (ptr))) pwd = ztrdup (ptr); иначе {pwd = NULL; pwd = metafy (zgetcwd () , -1, META_DUP); }
    
    

    oldpwd = ztrdup (pwd); /* инициализировать OLDPWD' = PWD' */

    Следовательно, если $HOME не установлен из среды, используется функция zgetcwd . Я не отслеживал это, но держу пари, он возвращает текущий рабочий каталог ;) . Наконец, $OLDPWD инициализируется с тем же значением.

Все примеры и фрагменты кода взяты из zsh 5.0.5-dev-0

0

Спасибо, mpy, за эту ценную информацию. Это помогло мне понять, как все работает.

Однако я нашел простое решение для возврата $ HOME, даже когда env is nul (так как это было частью моего задания). Следующая программа работает как талисман и использует флаг NON-POSIX функции glob (3) (поэтому будьте внимательны, проверяя, существует ли он в вашем glob.h).

#include <stdio.h>
#include <glob.h>

int                 main(void)
{
    glob_t          glob_info;
    unsigned int    i;
    int             ret;

    i = 0;
    if (!(ret = glob("~", GLOB_TILDE, NULL, &glob_info)))
    {
        while (i < glob_info.gl_pathc)
            printf("%s\n", glob_info.gl_pathv[i++]);
    }
    else
        printf("Glob error : %d\n", ret);
    return (0);
}

Обратите внимание, что glob(3) изначально не предназначен для этой цели.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .