123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- /*
- Write a program that lists the process ID and command name for all processes
- being run by the user named in the program’s command-line argument. (You may
- find the userIdFromName() function from Listing 8-1, on page 159, useful.) This can
- be done by inspecting the Name: and Uid: lines of all of the /proc/ PID /status files on
- the system. Walking through all of the /proc/ PID directories on the system requires the
- use of readdir(3), which is described in Section 18.8. Make sure your program
- correctly handles the possibility that a /proc/ PID directory disappears between the
- time that the program determines that the directory exists and the time that it tries
- to open the corresponding /proc/ PID /status file.
- */
- #define _DEFAULT_SOURCE
- #include <stdlib.h>
- #include <stdio.h>
- #include <pwd.h>
- #include <dirent.h>
- #include <sys/types.h>
- #include <stdbool.h>
- #include <linux/limits.h>
- #include <linux/sched.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- // BSD declared
- #include <err.h>
- #include "../common/logger.h"
- #define ARGUMENTS_COUNT 2
- #define ARGUMENT_USER_NAME 1
- #define PROC_DIR "/proc/"
- uid_t
- get_user_id_from_name(const char pw_name[static 1])
- {
- struct passwd *pwd = getpwnam(pw_name);
- if (pwd == NULL)
- return -1;
- return pwd->pw_uid;
- }
- struct process
- {
- char cmd_name[NAME_MAX];
- pid_t process_id;
- };
- #define MAX_LINE 100
- #define UID_STR "Uid:"
- #define NAME_STR "Name:"
- #define PID_STR "Pid:"
- #define LEN_STR(STR) sizeof(STR)/sizeof(char) - 1
- int
- main(int argc, char *argv[])
- {
- if (argc != ARGUMENTS_COUNT)
- log_error("Invalid argument");
- const char *user_name = argv[ARGUMENT_USER_NAME];
- const uid_t id = get_user_id_from_name(user_name);
- if (id == -1)
- log_error("Invalid user name");
- DIR* proc_dir = opendir(PROC_DIR);
- if (proc_dir == NULL)
- log_system_error("Failed to open proc directory");
- struct dirent *dirent;
- char path[PATH_MAX];
- const char *separator = " \t\n";
- while ((dirent = readdir(proc_dir)) != NULL)
- {
- if (dirent->d_type == DT_DIR)
- {
- if (atoi(dirent->d_name) == 0) continue;
- sprintf(path, "%s/%s/status", PROC_DIR, dirent->d_name);
- FILE *proc_status_fd = fopen(path, "r");
- if (proc_status_fd == NULL)
- {
- log_system_warning("failed to open file");
- continue;
- }
- char *line = NULL;
- size_t length;
- struct process process;
- bool is_user_process = false;
- while (getline(&line, &length, proc_status_fd) > 0)
- {
- if (strncmp(line, NAME_STR, LEN_STR(NAME_STR)) == 0)
- {
- char *argument = strpbrk(line, separator);
- if (argument) argument += strspn(argument, separator);
- else log_error("Failed to read an argument");
- char *argument_end = strpbrk(argument, separator);
- snprintf(process.cmd_name, argument_end - argument + 1, "%s",
- argument);
- }
- if (strncmp(line, UID_STR, LEN_STR(UID_STR)) == 0)
- {
- char *argument = strpbrk(line, separator);
- if (argument) argument += strspn(argument, separator);
- else log_error("Failed to read an argument");
- long long num = strtoll(argument, NULL, 10);
- if (num == id) is_user_process = true;
- }
- if (strncmp(line, PID_STR, LEN_STR(PID_STR)) == 0)
- {
- char *argument = strpbrk(line, separator);
- if (argument) argument += strspn(argument, separator);
- else log_error("Failed to read an argument");
- long long num = strtoll(argument, NULL, 10);
- process.process_id = num;
- }
- }
- free(line);
- fclose(proc_status_fd);
- if (is_user_process)
- {
- printf("process name: %s\n", process.cmd_name);
- printf("process id: %ld\n", process.process_id);
- puts("=================\n");
- }
- }
- }
- closedir(proc_dir);
- return EXIT_SUCCESS;
- }
|