Программирование в стандарте POSIX

PID TTY TIME CMD 1594


PID TTY TIME CMD 1594 ttyS4 00:00:02 sh 1645 ttyS4 00:00:00 sh 1654 ttyS4 00:02:45 rk.20.01 18356 ttyS4 00:00:00 prconecm 18357 ttyS4 00:00:00 sh 18358 ttyS4 00:00:00 ps
Листинг 7.1. Возможный результат использования утилиты ps.
Закрыть окно




ps -A -o ruser,user,pid,ppid,tty=TTY -o nice,vsz,args
Листинг 7.2. Пример использования утилиты ps.
Закрыть окно




RUSER USER PID PPID TTY NI VSZ COMMAND root root 1 0 ? 0 1372 init [5] root root 4 1 ? 19 0 [ksoftirqd_CPU0] root root 555 1 ? 0 1428 syslogd -m 0 root root 560 1 ? 0 1364 klogd -x rpc rpc 580 1 ? 0 1508 portmap rpcuser rpcuser 608 1 ? 0 1560 rpc.statd root root 743 1 ? 0 2620 /usr/sbin/sshd root root 776 1 ? 0 2200 xinetd -stayalive -reuse -pidfi root root 805 1 ? 0 1500 rpc.rquotad root root 810 1 ? 0 1504 rpc.mountd root root 897 1 ? 0 3236 /usr/libexec/postfix/master postfix postfix 906 897 ? 0 3384 nqmgr -l -n qmgr -t fifo -u -c root root 918 1 ? 0 1400 gpm -t ps/2 -m /dev/mouse root root 936 1 ? 0 1548 crond xfs xfs 968 1 ? 0 4432 xfs -droppriv -daemon nobody nobody 987 1 ? 0 36488 dictd 1.9.7: 0/0 root daemon 1022 1 ? 0 1404 /usr/sbin/atd root root 1057 1 ? 0 5768 cupsd root root 1064 1 tty1 0 1344 /sbin/mingetty tty1 root root 1070 1 ttyS2 0 1352 /sbin/agetty -i -L ttyS2 38400 root root 1072 1 ? 0 2300 login -- galat galat galat 1086 1072 ttyS4 0 2260 -sh root root 1124 1085 ? 0 16900 /usr/bin/kdm_greet postfix postfix 1826 897 ? 0 3304 pickup -l -t fifo -u -c galat galat 2013 1171 ttyS4 0 1940 /bin/sh -c ps -A -o user,pid,pp galat galat 2014 2013 ttyS4 0 2584 ps -A -o user,pid,ppid,tty=TTY
Листинг 7.3. Фрагмент возможного результата использования утилиты ps.
Закрыть окно






#include <unistd.h> pid_t getpid (void);
#include <unistd.h> pid_t getppid (void);
#include <unistd.h> pid_t getpgrp (void);
Листинг 7.4. getpid(), getppid() и getpgrp().
Закрыть окно




#include <unistd.h> int setpgid ( pid_t pid, pid_t pgid);
Листинг 7.5. Описание функции setpgid().
Закрыть окно




#include <unistd.h> pid_t setsid (void);
Листинг 7.6. Описание функции setsid().
Закрыть окно




#include <unistd.h> #include <sys/types.h> #include <stdio.h> int main (void) { pid_t ppid; pid_t pgid; /* Отменим буферизацию стандартного вывода */ setbuf (stdout, NULL); printf ("Атрибуты текущего процесса: pid: %d, ppid: %d, pgid: %d\n", getpid (), ppid = getppid (), pgid = getpgrp ()); /* Выделимся в новую группу */ if (setpgid (0, 0) != 0) { perror ("setpgid (0, 0)"); } printf ("Новая группа текущего процесса: %d\n", getpgrp ()); /* Попробуем создать новый сеанс */ if (setsid () == (pid_t) (-1)) { perror ("setsid от имени лидера группы"); } /* Вернемся в прежнюю группу */ if (setpgid (0, pgid) != 0) { perror ("setpgid (0, pgid)"); } printf (" Группа текущего процесса после повторной смены: %d\n", getpgrp ()); /* Повторим попытку создать новый сеанс */ if (setsid () == (pid_t) (-1)) { perror ("setsid от имени не-лидера группы"); } printf ("Группа текущего процесса после создания нового сеанса: %d\n", getpgrp ()); /* Попробуем сменить группу родительского процесса */ if (setpgid (ppid, 0) != 0) { perror ("setpgid (ppid, 0)"); } /* Попробуем установить несуществующий */ /* идентификатор группы процессов */ if (setpgid (0, ppid) != 0) { perror ("setpgid (0, ppid)"); } return (0); }
Листинг 7.7. Пример программы, использующей функции getpid(), getppid(), getpgrp(), setpgid(), setsid().
Закрыть окно




Атрибуты текущего процесса: pid: 11726, ppid: 11725, pgid: 1153 Новая группа текущего процесса: 11726 setsid от имени лидера группы: Operation not permitted Группа текущего процесса после повторной смены: 1153 Группа текущего процесса после создания нового сеанса: 11726 setpgid (ppid, 0): No such process setpgid (0, ppid): Operation not permitted
Листинг 7.8. Возможный результат работы программы, показанной в листинге 7.7.
Закрыть окно




#include <unistd.h> uid_t getuid (void);
#include <unistd.h> uid_t geteuid (void);
#include <unistd.h> gid_t getgid (void);
#include <unistd.h> gid_t getegid (void);
Листинг 7.9. Описание функций getuid(), geteuid(), getgid(), getegid().
Закрыть окно




#include <unistd.h> int getgroups ( int gidsetsize, gid_t grouplist []);
Листинг 7.10. Описание функции getgroups().
Закрыть окно




#include <unistd.h> int setuid (uid_t uid);
#include <unistd.h> int seteuid (uid_t uid);
Листинг 7.11. Описание функций setuid() и seteuid().
Закрыть окно




#include <unistd.h> int setgid (gid_t gid);
#include <unistd.h> int setegid (gid_t gid);
Листинг 7.12. Описание функций setgid() и setegid().
Закрыть окно




#include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h>
int main (void) { uid_t uid; int nsupgroups; gid_t *supgroupslist; int i; /* Отменим буферизацию стандартного вывода */ setbuf (stdout, NULL); printf ("Идентификаторы пользователя текущего процесса:\n" " реальный: %d, действующий: %d\n", uid = getuid (), geteuid ()); printf ("Идентификаторы группы текущего процесса:\n" " реальный: %d, действующий: %d\n", getgid (), getegid ()); printf ("Количество дополнительных групп текущего процесса: %d\n", nsupgroups = getgroups (0, supgroupslist)); if (nsupgroups > 0) { if ((supgroupslist = (gid_t *) malloc (nsupgroups * sizeof (gid_t))) == NULL) { perror ("MALLOC"); } else if (getgroups (nsupgroups, supgroupslist) == (-1)) { perror ("GETGROUPS"); } else { /* Выдадим идентификаторы дополнительных */ /* групп процесса */ printf ("Идентификаторы дополнительных групп текущего процесса:\n"); for (i = 0; i < nsupgroups; i++) { printf (" %d", supgroupslist [i]); } printf ("\n"); } } /* Попробуем переустановить идентификатор */ /* пользователя процесса */ if (setuid ((uid_t) 1) != 0) { perror ("setuid (1)"); } printf ("Идентификаторы пользователя текущего процесса после первой смены:\n" " реальный: %d, действующий: %d\n", getuid (), geteuid ()); /* Попробуем вернуть прежний идентификатор */ /* пользователя процесса */ if (setuid (uid) != 0) { perror ("setuid (uid)"); } printf ("Идентификаторы пользователя текущего процесса после второй смены:\n" " реальный: %d, действующий: %d\n", getuid (), geteuid ()); /* Попробуем сменить действующий идентификатор */ /* с помощью функции seteuid() */ if (seteuid ((uid_t) 1) != 0) { perror ("seteuid (1)"); } printf ("Идентификаторы пользователя текущего процесса после третьей смены:\n" " реальный: %d, действующий: %d\n", getuid (), geteuid ()); return (0); }
Листинг 7.13. Пример использования функций опроса и изменения идентификаторов пользователя процесса.
Закрыть окно




Идентификаторы пользователя текущего процесса: реальный: 108, действующий: 108 Идентификаторы группы текущего процесса: реальный: 3, действующий: 3 Количество дополнительных групп текущего процесса: 1 Идентификаторы дополнительных групп текущего процесса: 3 setuid (1): Operation not permitted Идентификаторы пользователя текущего процесса после первой смены: реальный: 108, действующий: 108 Идентификаторы пользователя текущего процесса после второй смены: реальный: 108, действующий: 108 seteuid (1): Operation not permitted Идентификаторы пользователя текущего процесса после третьей смены: реальный: 108, действующий: 108
Листинг 7.14. Возможный результат работы программы, показанной в листинге 7.13 и запущенной от имени обычного пользователя.
Закрыть окно




Идентификаторы пользователя текущего процесса: реальный: 0, действующий: 0 Идентификаторы группы текущего процесса: реальный: 0, действующий: 0 Количество дополнительных групп текущего процесса: 7 Идентификаторы дополнительных групп текущего процесса: 0 1 2 3 4 6 10 Идентификаторы пользователя текущего процесса после первой смены: реальный: 1, действующий: 1 setuid (uid): Operation not permitted Идентификаторы пользователя текущего процесса после второй смены: реальный: 1, действующий: 1 Идентификаторы пользователя текущего процесса после третьей смены: реальный: 1, действующий: 1
Листинг 7.15. Возможный результат работы программы, показанной в листинге 7.13 и запущенной от имени суперпользователя.
Закрыть окно




Идентификаторы пользователя текущего процесса: реальный: 108, действующий: 1 Идентификаторы группы текущего процесса: реальный: 3, действующий: 1 Количество дополнительных групп текущего процесса: 1 Идентификаторы дополнительных групп текущего процесса: 3 Идентификаторы пользователя текущего процесса после первой смены: реальный: 108, действующий: 1 Идентификаторы пользователя текущего процесса после второй смены: реальный: 108, действующий: 108 Идентификаторы пользователя текущего процесса после третьей смены: реальный: 108, действующий: 1
Листинг 7.16. Возможный результат работы программы, показанной в листинге 7.13 и запущенной от имени обычного пользователя после взведения в режиме выполнимого файла бита ПДИП.
Закрыть окно




#include <sys/stat.h>> mode_t umask (mode_t cmask);
Листинг 7.17. Описание функции umask().
Закрыть окно




umask 0 umask -S umask -- -x umask
Листинг 7.18. Пример использования служебной программы umask.
Закрыть окно




u=rwx,g=rwx,o=rwx 0111
Пример 7.19. Листинг 7.19. Возможный результат использования служебной программы umask.
Закрыть окно




#include <unistd.h> pid_t fork (void);
Листинг 7.20. Описание функции fork().
Закрыть окно




int main ( int argc, char *argv []);
Пример 7.21. Заголовок функции main() C-программы.
Закрыть окно




#include <unistd.h> extern char **environ; int execl (const char *path, const char *arg0, ... /*, (char *) 0 */); int execv (const char *path, char *const argv []); int execle (const char *path, const char *arg0, ... /*, (char *) 0, char *const envp [] */); int execve (const char *path, char *const argv [], char *const envp []); int execlp (const char *file, const char *arg0, ... /*, (char *) 0 */); int execvp (const char *file, char *const argv []);
Пример 7.22. Описание функций семейства exec().
Закрыть окно




#include <sys/wait.h> pid_t wait (int *stat_loc); pid_t waitpid ( pid_t pid, int *stat_loc, int options);
Пример 7.23. Описание функций семейства wait().
Закрыть окно




#include <stdlib.h> void exit (int status); void _Exit (int status); #include <unistd.h> void _exit (int status);
Пример 7.24. Описание функций семейства exit().
Закрыть окно




#include <stdlib.h> int atexit (void (*func) (void));
Пример 7.25. Описание функции atexit().
Закрыть окно




#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/wait.h>
static void atefunc (void) { /* Перед завершением выдадим информацию о */ /* процессах */ printf ("Ситуация перед завершением родительского процесса\n"); (void) system ("ps -o pid,ppid,vsz,args"); }
int main (void) { int pid; int stat; /* Отменим буферизацию стандартного вывода */ setbuf (stdout, NULL); /* Зарегистрируем обработчик завершения процесса */ if (atexit (atefunc) != 0) { perror ("ATEXIT"); exit (1); } /* Создадим новый процесс */ if ((pid = fork ()) < 0) { perror ("FORK"); exit (2); } else if (pid == 0) { /* Порожденный процесс */ /* Выполним служебную программу ps */ printf ("Ситуация с точки зрения порожденного процесса\n"); (void) execl ("/bin/ps", "ps", "-o", "pid,ppid,args", (char *) 0); perror ("EXEC"); exit (3); /* execl() завершился неудачей */ } else { /* Родительский процесс */ sleep (1); /* Вероятно, порожденный процесс уже */ /* завершился */ /* Посмотрим на текущую ситуацию */ printf ("Ситуация перед вызовом waitpid() в родительском процессе\n"); (void) system ("ps -o pid,ppid,vsz,args"); (void) waitpid (pid, &stat, 0); printf ("Статус завершения порожденного процесса с идентификатором %d: %d\n", pid, stat); } return 0; }
Пример 7.26. Пример использования функций порождения и завершения процессов.
Закрыть окно




Ситуация с точки зрения порожденного процесса PID PPID COMMAND 6123 1072 -sh 29568 6123 prog30 29569 29568 ps -o pid,ppid,args Ситуация перед вызовом waitpid() в родительском процессе PID PPID VSZ COMMAND 6123 1072 2260 -sh 29568 6123 1340 prog30 29569 29568 0 [ps <defunct>] 29570 29568 2584 ps -o pid,ppid,vsz,args Статус завершения порожденного процесса с идентификатором 29569: 0 Ситуация перед завершением родительского процесса PID PPID VSZ COMMAND 6123 1072 2260 -sh 29568 6123 1340 prog30 29571 29568 2584 ps -o pid,ppid,vsz,args
Пример 7.27. Возможный результат работы программы, использующей функции порождения и завершения процессов.
Закрыть окно



Содержание раздела