/src/functions.c

https://gitlab.com/dtluna/Course · C · 223 lines · 191 code · 32 blank · 0 comment · 26 complexity · a5e97bcf4dc9c482d09e66890db9f781 MD5 · raw file

  1. #include "procinfo.h"
  2. #include "functions.h" // <sys/types.h> <dirent.h>
  3. #include "errors.h"
  4. #include "system_info.h"
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include "alloc.h"
  11. int filter_dir(const struct dirent* entry)
  12. {
  13. if (( DT_DIR == entry->d_type ) && ( is_number(entry->d_name )))
  14. return 1;
  15. else
  16. return 0;
  17. }
  18. bool is_number (const char* string)
  19. {
  20. char* endptr = alloc_str(strlen(string));
  21. char* endptr_copy = endptr;
  22. long int number = strtol(string, &endptr, 10);
  23. if ( ( 0 == number ) && ( 0 == strcmp(string, endptr) ) )
  24. {
  25. free(endptr_copy);
  26. return false;
  27. }
  28. else
  29. {
  30. free(endptr_copy);
  31. return true;
  32. }
  33. }
  34. unsigned int get_pid_dirents_size (const struct dirent** pid_dirents)
  35. {
  36. unsigned int i = 0;
  37. while(NULL != pid_dirents[i])
  38. i++;
  39. return i;
  40. }
  41. unsigned int get_pid_dirnames (char*** pid_dirnames)
  42. {
  43. struct dirent** pid_entries = get_pid_dirents();
  44. unsigned int pid_entries_size = get_pid_dirents_size(pid_entries);
  45. *pid_dirnames = alloc_str_array(pid_entries_size);
  46. for (unsigned int i = 0; i < pid_entries_size; ++i)
  47. (*pid_dirnames)[i] = pid_entries[i]->d_name;
  48. free(pid_entries);
  49. return pid_entries_size;
  50. }
  51. struct dirent** get_pid_dirents ()
  52. {
  53. struct dirent** namelist = NULL;
  54. scandir_err(scandir(".", &namelist, &filter_dir, &pid_dir_compare));
  55. return namelist;
  56. }
  57. int pid_dir_compare (const struct dirent **first_entry, const struct dirent **second_entry)
  58. {
  59. pid_t first_pid = atoi((*first_entry)->d_name);
  60. pid_t second_pid = atoi((*second_entry)->d_name);
  61. return (first_pid - second_pid);
  62. }
  63. char* correct_comm (char* comm)
  64. {
  65. size_t len = strlen(comm);
  66. comm[len-1] = '\0';
  67. for (size_t i = 0; i < len; ++i)
  68. {
  69. comm[i] = comm[i+1];
  70. }
  71. return comm;
  72. }
  73. time_t get_proc_time ()
  74. {
  75. clock_t utime = 0, stime = 0;
  76. FILE* stat_file = fopen("./stat", "r");
  77. fopen_err(stat_file);
  78. fscanf(stat_file,
  79. "%*d %*s %*c %*d %*d"
  80. "%*d %*d %*u %*u %*lu"
  81. "%*lu %*lu %lu %lu",
  82. &utime, &stime);
  83. fclose_err(fclose(stat_file));
  84. time_t proc_time = ((utime+stime)/sysconf(_SC_CLK_TCK));
  85. return proc_time;
  86. }
  87. time_t get_uptime ()
  88. {
  89. time_t uptime = 0;
  90. FILE* uptime_file = fopen("/proc/uptime", "r");
  91. fopen_err(uptime_file);
  92. fscanf(uptime_file, "%lu", &uptime);
  93. fclose_err(fclose(uptime_file));
  94. return uptime;
  95. }
  96. time_t get_cpu_time ()
  97. {
  98. clock_t user = 0, nice = 0, system_time = 0, idle = 0;
  99. FILE* cpu_stat_file = fopen("/proc/stat", "r");
  100. fopen_err(cpu_stat_file);
  101. fscanf(cpu_stat_file,
  102. "%*s %lu %lu %lu %lu",
  103. &user, &nice, &system_time, &idle);
  104. fclose_err(fclose(cpu_stat_file));
  105. time_t cpu_time = (user+nice+system_time+idle)/sysconf(_SC_CLK_TCK);
  106. return cpu_time;
  107. }
  108. char* procinfo_to_string (const struct procinfo p_info)
  109. {
  110. char* string = alloc_str(2*MAX_CMDLINE_LEN);
  111. sprintf(string,
  112. "%5d "//pid
  113. "%c " //state
  114. "%5d " //ppid
  115. "%3d " //cpu usage
  116. "%5ld "//priority
  117. "%5ld "//nice
  118. "%5ld "//num_threads
  119. "%6llu "//uptime
  120. "%10lu "//vsize
  121. "%7ld "//rss
  122. "%s ",//comm
  123. p_info.pid, p_info.state,
  124. p_info.ppid, p_info.cpu_usage,
  125. p_info.priority, p_info.nice,
  126. p_info.num_threads, p_info.uptime,
  127. p_info.vsize, p_info.rss, p_info.comm);
  128. return string;
  129. }
  130. void fill_boot_time()
  131. {
  132. update_sys_info();
  133. time_t tse = time(NULL);
  134. sys_info.boot_time = tse - sys_info.uptime;
  135. }
  136. pid_t find_process (const struct procinfo* p_info_arr, const unsigned int size, const char* proc_name)
  137. {
  138. for (int i = 0; i < size; ++i)
  139. {
  140. if (0 == strcmp(p_info_arr[i].comm, proc_name))
  141. return p_info_arr[i].pid;
  142. }
  143. fprintf(stderr, "Error: no such process!\n");
  144. return -1;
  145. }
  146. void enter_decimal (int* number, char* msg)
  147. {
  148. char n_string[7];
  149. do
  150. {
  151. printf( "%s ", msg);
  152. get_string(n_string, 7);
  153. if (is_number(n_string))
  154. {
  155. *number = atoi(n_string);
  156. return;
  157. }
  158. else
  159. {
  160. fprintf(stderr, "Error: not a decimal number!\n");
  161. continue;
  162. }
  163. } while(1);
  164. }
  165. bool should_continue (char* msg)
  166. {
  167. char answer [256];
  168. do
  169. {
  170. printf("%s(yes,no)?\n", msg);
  171. get_string(answer, 256);
  172. if ( (0 == strcmp(answer, "yes")) || (0 == strcmp(answer, "y")) )
  173. return true;
  174. if ( (0 == strcmp(answer, "no")) || (0 == strcmp(answer, "n")) )
  175. return false;
  176. puts("Invalid input. Try once again.");
  177. }while (1);
  178. }
  179. void remove_newline(char* string)
  180. {
  181. int newline_pos = strlen(string)-1;
  182. if ('\n' == string[newline_pos])
  183. string[newline_pos] = '\0';
  184. }
  185. void get_string (char* string, size_t size)
  186. {
  187. fflush(stdin);
  188. fgets(string, size, stdin);
  189. remove_newline(string);
  190. return;
  191. }