LINUX.ORG.RU

Получить домашнюю папку запустившего программу пользователя (язык С) .

 


0

2

Подскажите как получить внутри программы домашнюю папку запустившего программу пользователя.Причем использовать glib нельзя (его нет в зависимостях). Используя язык C .

#include <stdio.h>
#include <pwd.h>
#include <unistd.h>

int
main()
{
	char *u = getlogin();
	struct passwd *p = getpwnam(u);
	printf("home: %s\n", p->pw_dir);
	return 0;
}

использовать glib нельзя (его нет в зависимостях)

Ну и фиг с ним, используй libc.

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

Ты не перепутал glib и glibc?

Без понятия. ;)

  • glibc is a core C runtime library. It provides things like printf(3) and fopen(3).
  • glib is an object-based event loop and utility library written in C.
  • gnulib is a library that provides an adapter from the POSIX API to the native API.

Что имел в виду ТС – не знаю.

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

Твой способ не совсем правильный. $HOME в любом случае приоритетнее, а если даже его нет, то я не уверен, что лучше: читать из passwd или принять home = / (и получать ошибки при попытках в него что-то записать).

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

Тут вот в чём фишка:

запустившего программу пользователя

Т.ч. getenv даст неправильный ответ. Но ты прав – у меня там ошибка. Надо брать из getpwuid:

#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>

int
main()
{
	struct passwd *uid = getpwuid(getuid()); // geteuid?
	printf("getpwuid: %s\n", uid->pw_dir);   // correct result

	struct passwd *nam = getpwnam(getlogin());
	printf("getpwnam: %s\n", nam->pw_dir);   // wrong result

	printf("getenv: %s\n", getenv("HOME"));  // wrong result

	return 0;
}
tmp % ./h
getpwuid: /Users/dima
getpwnam: /Users/dima
getenv: /Users/dima
tmp % sudo ./h
getpwuid: /var/root
getpwnam: /Users/dima
getenv: /Users/dima

PS: я уже забыл в чём конкретно разница между getuid и geteuid. Оба дают правильный ответ под sudo.

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

запустившего

Термин…ология. Что есть запуск? Шебанг с судо?

uid и euid?

Это связано с suid: uid - запускающий пользователь, euid - uid файла/бинарника с suid.

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

Ну уж нет, тащить эту чушь за пределы гуи точно не надо.

Вопрос в пустоту - чем GUI принципиально отличается от не GUI?

В контексте топика речь про XDG’шные каталоги ~/.config/appname и /.local/share/appname вместо помойки из дотфайлов в ~. Это правильный подход независимо от GUI’шности.

anonymous
()

В общем случае это невозможно. Программа запущена в контейнере с euid 100500. В /etc/passwd внутри контейнера пользователя с таким uid нет. Переменная окружения HOME содержит путь к несуществующей директории

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

Тут вот в чём фишка:
запустившего программу пользователя
Т.ч. getenv даст неправильный ответ.

С чего это он даст неправильный? Хотя тут есть некоторая двусмысленность терминологии, но всё-таки записи в passwd это не «запустивший пользователь» а «логинящийся пользователь». И, учитывая контекст, пользователь тут - вовсе не uid, а текущее рабочее окружение. У uid-а homedir-а вообще нет и быть не может, а то, что ты ищешь - «homedir первого логина в списке, у которого uid совпадает с текущим». Да, их может быть больше одного, и это полностью нормальная ситуация. Предыдущий вариант с getpwnam был более адекватен в этом плане, но и он неправильный по той же причине.

tmp % sudo ./h

Тут проблема не в том, что ты неправильно получаешь home, а в том, что ты запустил дефективный софт по названием sudo, который устраивает всякую чушь. Да, home там должен быть именно /Users/dima.

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

Вопрос в пустоту - чем GUI принципиально отличается от не GUI?

Под гуи имелся ввиду оплот гномеров, вайландеров и прочих некомпетентных личностей, устроивших там помойку. А «негуи» - пока ещё свободную от этой инфекции территорию.

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

Возможно, конечно. Эта самая несуществующая директория и будет home. То, что её нет, в целом ситуацию не меняет. В passwd смотреть не надо, я уже выше писал почему.

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

то я не уверен, что лучше: читать из passwd или принять home = / (и получать ошибки при попытках в него что-то записать).

Ничего из вышеперечисленного. Хомдир задаётся исключительно $HOME, никаких дефолтов у него нет и придумывать их не надо. Если хочется читать/писать в HOME, а $HOME не установлен, просто не читай/пиши. Если нужно читать/писать, то падай.

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

Ну уж нет, тащить эту чушь за пределы гуи точно не надо.

Какая разница GUI или что-то другое. $XDG_DATA_HOME, $XDG_CONFIG_HOME, $XDG_CACHE_HOME – база для хранения данных ПО. Любой кто хранит данные в ~/.myapp – говнюк полный. Остальное не менее важно.

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

Т.ч. getenv даст неправильный ответ.

Что значит «неправильный»? Если программа хочет узнать где домашний каталог пользователя, то по-уму ей сначала надо проверить существует ли в окружении переменная HOME. Если есть — использовать её значение, и только если переменной HOME нет, то вызывать getpwuid(). Какой user id указывать — реальный или эффективный — зависит от программы. Большинству обычных программ (которые не меняют user id по ходу исполнения) — пофигу, они совпадают. Если программа меняет user id — то надо разбираться а чего именно хочет добиться автор программы — получить каталог того пользователя, который запустил программу, или того пользователя, от имени которого программа работает в данный момент. Но в любом случае, начинать надо с HOME.

Но я бы начал с вопроса: а зачем ТС домашний каталог пользователя? Если для поиска конфигов или сохранения кеша/данных, то надо для начала курить XDG, а уж там явно написано, что если XDG_??? переменная не установлена, то дефолтное значение конструируется из переменной HOME.

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

У меня уже давно есть rule of thumb: если программа мусорит своим барахлом прямо в ~/, то лучше её поскорее удалить. Есть исключения, конечно, вроде Firefox, в котором скоро должны доделать поддержку XDG Base Directory, или cargo, который нечем заменить (и там можно переопределить каталог).

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

Всё наоборот, тот же mc раньше очень удобно всё складывал в .mc, а теперь раскидан по этим дурацким .local итд, крайне неудобно. Файрфокс хорошо что до сих пор пишет в .mozilla, если они хотят это испортить - осуждаю. Впрочем, частично уже испортили, как я какое-то время назад заметил - оно ещё в .cache что-то создаёт, и из-за этого для удаления профиля недостаточно удалить одну директорию, надо лазить где оно ещё наспамить успело.

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

Всё наоборот, тот же mc раньше очень удобно всё складывал в .mc, а теперь раскидан по этим дурацким .local итд, крайне неудобно.

Это разделение конфигурации и данных, не представляю, как оно может быть неудобным. Конкретно в MC тебе вообще не надо лезть в ~/.local/share/mc, там чисто служебные файлы.

Файрфокс хорошо что до сих пор пишет в .mozilla, если они хотят это испортить - осуждаю.

Насколько я помню, старый вариант будет тоже поддерживаться. Поддержка XDG тоже будет, вероятно, в стиле Chromium, когда в $XDG_CONFIG_HOME валяются вместе конфигурация и данные, но не слежу особо, возможно, и сумеют разделить как-то.

Впрочем, частично уже испортили, как я какое-то время назад заметил - оно ещё в .cache что-то создаёт, и из-за этого для удаления профиля недостаточно удалить одну директорию, надо лазить где оно ещё наспамить успело.

Любишь включать в резервные копии всякий мусор? ~/.cache легко и игнорировать, и просто грохнуться целиком без опасений потерять что-то сломать.

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

Конкретно в MC тебе вообще не надо лезть в ~/.local/share/mc, там чисто служебные файлы.

Это тебе не надо а я там редактировал схемы подсветки. И вообще, .local/share это двойной идиотизм, мало того что из удобного корня убрали в какую-то директорию второй вложенности с непонятным бессмысленным названием, так там ещё и каша внутри из тех же конфигов, кешей и файлов данных (речь не про конкретно mc, это у всех), только, в отличие от схемы «всё в корне», когда на втором уровне вложенности оно было структурировано по категории файлов, тут оно лежит просто в виде каши.

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

Это тебе не надо а я там редактировал схемы подсветки

Так и знал, что про это скажешь. Странно вообще, что схемы не в ~/.config, но тут MC не одинок, у nano такая же логика.

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

убрали в какую-то директорию второй вложенности

С одной стороны, эта вложенность используется, поскольку там рядом прописались всякие bin, state, у многих ещё lib. Но тогда было бы логично и config туда закинуть. С другой стороны, если хочешь переопределить расположение ~/.local/share, то надо оставить симлинк для кривых приложений, и эта вложенность становится неудобством.

В общем, не всё гладко, но стандарт есть стандарт, он прижился, и это уже не та помойка из скрытых файлов в домашнем каталоге. Я бы ещё сделал все эти каталоги не скрытыми, потому что дот-файлы — это просто рак, который появился не от большого ума.

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

А причина на самом деле вот какая. Само ~/.local планировалось как юзерский аналог /usr (оттуда и bin/lib). Но вот какое дело, /usr/share это место для хранения, в том числе, дефолтных конфигов, а место для хранения настроенных конфигов - /etc (которому аналог ~/.config). В контексте системы разделение понятно - дефолтные конфиги ставит пакетный менеджер, а настроенные - могут редактироваться администратором. В контексте юзера это разделение выглядит сомнительно - дефолты всё так же хранятся в /usr/share, дублировать их в ~/.local/share незачем. Остаётся одно единственное вменяемое применение: класть в ~/.local/share дефолты софта, установленного самим юзером себе в $HOME с префиксом $HOME/.local (например, через ./configure --prefix=$HOME/.local && make install). Собственно, ~/.local/bin и ~/.local/lib аналогично. То, что туда что-то пишут проги про запуске (не инсталляторы) - некорректное поведение. То, что установленные общесистемно проги оттуда что-то читают - ну, наверно допустимо (хотя я не уверен), но только если юзер сам решил таким образом подменить /usr/share. То есть, дефолтно никакого ~/.local/share существовать не должно, он может появиться только при явном на то желании юзера.

Если бы он существовал именно в таком виде - я бы его не осуждал, более того у меня было ~/usr/ для аналогичной цели когда-то (распаковывал туда deb-пакеты), а сейчас есть ~/DEV/{lib|include|man|src}/ для локальной компиляции при разработке.

Программы, установленные системным пакетным менеджером, вполне могли бы обойтись двумя директориями, какими-нить ~/.state/NAME и ~/.cache/NAME, причём большинству - только первая. И незачем делать всякие $XDG_XXX_DIR, это только добавляет лишнюю логику в куче мест системы, вполне нормально обращаться к ним через $HOME. Тогда можно точно знать, что вот есть максимум два места, где можно искать автосозданные прогой файлы. А кому надо другое место - есть симлинки.

Впрочем, некоторые я бы всё равно оставил в корне например ~/.ssh.

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

Нет, /etc/passwd это список логинов. А источник данных о текущем юзере это getuid() и похожие функции, а также getenv(). Юзер совершенно не обязательно логинился через штатные способы, он может быть синтетическим, сделанным на лету какой-то рутовой прогой. Да и не только рутовой, я иногда запускаю что-то в виде

HOME=$HOME/subdir /path/to/executable
И все нормальные программы, как и положено, считают home-ом указанную директорию и не устраивают самодеятельность с парсингом passwd.

firkax ★★★★★
()