LINUX.ORG.RU

Как узнать владельца процесса?


0

0

Какой самый простой способ узнать из программы на C запущен ли экзешник с заданным именем и от имени какого пользователя он запущен? Помимо анализа /proc/*/exe для поиска программы с последующим поиском HOME=... в /proc/.../environ

Заранее спасибо.

★★★★★
Ответ на: комментарий от Demon37

> uid_t getuid();

Спасибо, но это даст владельца текущего процесса. А мне, наоборот, нужно узнать не запущен ли уже другой экземпляр программы от имени того же пользователя.

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

> kill(pid, 0);

В системных манах такой функции нет, можно ссылку? И где взять pid?

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

>Спасибо, но это даст владельца текущего процесса. А мне, наоборот, нужно узнать не запущен ли уже другой экземпляр программы от имени того же пользователя.

Неправильно понял вопрос, извиняюсь. Тогда всё-таки проще будет парсить proc. Хотя можно было бы, наверное, заморочиться мьютексами %)

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

> Тогда всё-таки проще будет парсить proc.

Как узнать владельца процесса менее запутанным способом, чем поиском в /proc/.../environ "\000HOME=$HOME\000" ?

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

> Как узнать владельца процесса менее запутанным способом, чем поиском в /proc/.../environ "\000HOME=$HOME\000" ?

Владелец псевдофайлов в /proc/$PID и есть владелец процесса. Так что stat(2) на соответствующую директорию в /proc и всё.

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

> popen + ps + ...

Спасибо. Тогда уж сразу popen + (ps | grep имяфайла). Сама-то ps каким образом этот список получает?

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

> Владелец псевдофайлов в /proc/$PID и есть владелец процесса. Так что stat(2) на соответствующую директорию в /proc и всё.

Спасибо. До 1-го я уже дошёл. За stat спасибо.

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

>Спасибо. Тогда уж сразу popen + (ps | grep имяфайла). Сама-то ps каким образом этот список получает?

Да в принципе ничего страшного бы не случилось, если б владельца получал таким образом, ведь ps в любой дистр линукса входит:

ps --pid <PID> --format user --no-headers

Но более правильный способ уже Иван подсказал, опередив меня. :)

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

> и что это даст?

Есть ли процесс pid и принадлежит ли он тому же пользователю, который kill запустил. Ответ был не на топик, а на ту фразу, которую я процитировал.

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

> Есть ли процесс pid и принадлежит ли он тому же пользователю, который kill запустил.

Спасибо. Просто из 1-го поста это было непонятно. И я правильно понимаю, что этот трюк не сработает, если запускать программу от имени суперпользователя?

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

> И я правильно понимаю, что этот трюк не сработает, если запускать программу от имени суперпользователя?

Не сработает, поэтому надо сначала geteuid() глянуть. Боюсь, единственный портабельный способ выяснять подобные вещи - запускать ps и парсить вывод.

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

> Боюсь, единственный портабельный способ выяснять подобные вещи - запускать ps и парсить вывод.

Вообще-то, вполне можно обойтись и без запуска внешних приложений: выдрать кусок кода из ps и вставить в свою программу.

Я точно так же делал, когда возникла необходимость при запуске процесса убивать одноименные (чтобы не висело несколько демонов). Выдрал кусочек из pkill'а и оформил как отдельную функцию. Всего на полстраницы кода получилось. Здесь можно поступить также.

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

>Вообще-то, вполне можно обойтись и без запуска внешних приложений: выдрать кусок кода из ps и вставить в свою программу.

Снижает переносимость.

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

да, но разве веток ядер сильно много? :). Везде ветка 2.6.x. Хотя хрен знает ядрописателей, они могут и такое сломать если захотят...

true_admin ★★★★★
()

А есть доступ к исходникам?

Тогда как-то так:

int fd=open("/var/run/my.pid",O_RDWR|O_CREAT,0644);

if (flock(fd,LOCK_NB|LOCK_EXCL)==-1) {
   if (errno==EWOULDBLOCK) {
    //Процесс уже запущен
    struct stat buf;
    fstat(fd,&buf);
    printf("Already started by UID %d\n",buf.st_uid);
    exit(1);
   }
}
else {fchown(fd,getuid(),getgid());}

можно еще PID писать в этот файл. для надежности.

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

Спасибо.

> /var/run/my.pid

Цель противоположная: чтобы каждый пользователь мог запустить по 1 копии программы. Кроме того, /var/run/ в некоторых дистрибутивах доступен только руту. Поэтому тут лучше что-нибудь вроде ~/.имяпрограммы/run.lock. Лично мне такой подход не нравится, поэтому я и спросил о других способах.

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

> хрен знает ядрописателей, они могут и такое сломать если захотят...

:)

Скорее тогда в ядре долго будут на выбор 2 системы. А ps с остальными программами будут содержать 2 блока: для старых ядер и для новых.

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

> Линуксовый, емнип, бегает по проку.

Спасибо.

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

> Цель противоположная: чтобы каждый пользователь мог запустить по 1 копии программы.

уу, что ж ты сразу не сказал. Тогда в чём сложности? Создал /tmp/<progname>_<uid>.pid и смотришь есть он и, если есть, валидный ли он а не остался висеть после старого запуска. А ещё лучше юзай man 3 lockf на этот файл. Надёжно и портабельно. Только смотри чтобы при execve лок не унаследовал вызываемый процесс.

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

А что мешает имя этого файла сделать каким угодно? man snprintf ;)

<username>.pid

flock просто гарантирует что это процесс все еще жив, и довольно портабельно.

OxiD ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.