exercise_12_1.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. Write a program that lists the process ID and command name for all processes
  3. being run by the user named in the program’s command-line argument. (You may
  4. find the userIdFromName() function from Listing 8-1, on page 159, useful.) This can
  5. be done by inspecting the Name: and Uid: lines of all of the /proc/ PID /status files on
  6. the system. Walking through all of the /proc/ PID directories on the system requires the
  7. use of readdir(3), which is described in Section 18.8. Make sure your program
  8. correctly handles the possibility that a /proc/ PID directory disappears between the
  9. time that the program determines that the directory exists and the time that it tries
  10. to open the corresponding /proc/ PID /status file.
  11. */
  12. #define _DEFAULT_SOURCE
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <pwd.h>
  16. #include <dirent.h>
  17. #include <sys/types.h>
  18. #include <stdbool.h>
  19. #include <linux/limits.h>
  20. #include <linux/sched.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. #include <string.h>
  24. // BSD declared
  25. #include <err.h>
  26. #include "../common/logger.h"
  27. #define ARGUMENTS_COUNT 2
  28. #define ARGUMENT_USER_NAME 1
  29. #define PROC_DIR "/proc/"
  30. uid_t
  31. get_user_id_from_name(const char pw_name[static 1])
  32. {
  33. struct passwd *pwd = getpwnam(pw_name);
  34. if (pwd == NULL)
  35. return -1;
  36. return pwd->pw_uid;
  37. }
  38. struct process
  39. {
  40. char cmd_name[NAME_MAX];
  41. pid_t process_id;
  42. };
  43. #define MAX_LINE 100
  44. #define UID_STR "Uid:"
  45. #define NAME_STR "Name:"
  46. #define PID_STR "Pid:"
  47. #define LEN_STR(STR) sizeof(STR)/sizeof(char) - 1
  48. int
  49. main(int argc, char *argv[])
  50. {
  51. if (argc != ARGUMENTS_COUNT)
  52. log_error("Invalid argument");
  53. const char *user_name = argv[ARGUMENT_USER_NAME];
  54. const uid_t id = get_user_id_from_name(user_name);
  55. if (id == -1)
  56. log_error("Invalid user name");
  57. DIR* proc_dir = opendir(PROC_DIR);
  58. if (proc_dir == NULL)
  59. log_system_error("Failed to open proc directory");
  60. struct dirent *dirent;
  61. char path[PATH_MAX];
  62. const char *separator = " \t\n";
  63. while ((dirent = readdir(proc_dir)) != NULL)
  64. {
  65. if (dirent->d_type == DT_DIR)
  66. {
  67. if (atoi(dirent->d_name) == 0) continue;
  68. sprintf(path, "%s/%s/status", PROC_DIR, dirent->d_name);
  69. FILE *proc_status_fd = fopen(path, "r");
  70. if (proc_status_fd == NULL)
  71. {
  72. log_system_warning("failed to open file");
  73. continue;
  74. }
  75. char *line = NULL;
  76. size_t length;
  77. struct process process;
  78. bool is_user_process = false;
  79. while (getline(&line, &length, proc_status_fd) > 0)
  80. {
  81. if (strncmp(line, NAME_STR, LEN_STR(NAME_STR)) == 0)
  82. {
  83. char *argument = strpbrk(line, separator);
  84. if (argument) argument += strspn(argument, separator);
  85. else log_error("Failed to read an argument");
  86. char *argument_end = strpbrk(argument, separator);
  87. snprintf(process.cmd_name, argument_end - argument + 1, "%s",
  88. argument);
  89. }
  90. if (strncmp(line, UID_STR, LEN_STR(UID_STR)) == 0)
  91. {
  92. char *argument = strpbrk(line, separator);
  93. if (argument) argument += strspn(argument, separator);
  94. else log_error("Failed to read an argument");
  95. long long num = strtoll(argument, NULL, 10);
  96. if (num == id) is_user_process = true;
  97. }
  98. if (strncmp(line, PID_STR, LEN_STR(PID_STR)) == 0)
  99. {
  100. char *argument = strpbrk(line, separator);
  101. if (argument) argument += strspn(argument, separator);
  102. else log_error("Failed to read an argument");
  103. long long num = strtoll(argument, NULL, 10);
  104. process.process_id = num;
  105. }
  106. }
  107. free(line);
  108. fclose(proc_status_fd);
  109. if (is_user_process)
  110. {
  111. printf("process name: %s\n", process.cmd_name);
  112. printf("process id: %ld\n", process.process_id);
  113. puts("=================\n");
  114. }
  115. }
  116. }
  117. closedir(proc_dir);
  118. return EXIT_SUCCESS;
  119. }