dmesg.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/klog.h>
  5. #include <unistd.h>
  6. /**
  7. * @brief 识别dmesg程序的第一个选项参数
  8. *
  9. * @param arg dmesg命令第一个选项参数
  10. * @return int 有效时返回对应选项码,无效时返回 -1
  11. */
  12. int getoption(char *arg) {
  13. if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
  14. return 0;
  15. else if (!strcmp(arg, "-c") || !strcmp(arg, "--read-clear"))
  16. return 4;
  17. else if (!strcmp(arg, "-C") || !strcmp(arg, "--clear"))
  18. return 5;
  19. else if (!strcmp(arg, "-l") || !strcmp(arg, "--level"))
  20. return 8;
  21. return -1;
  22. }
  23. /**
  24. * @brief 识别dmesg程序的第二个选项参数
  25. *
  26. * @param arg dmesg命令第一个选项参数
  27. * @return int 有效时返回设置的日志级别,无效时返回 -1
  28. */
  29. int getlevel(char *arg) {
  30. if (!strcmp(arg, "EMERG") || !strcmp(arg, "emerg"))
  31. return 0;
  32. else if (!strcmp(arg, "ALERT") || !strcmp(arg, "alert"))
  33. return 1;
  34. else if (!strcmp(arg, "CRIT") || !strcmp(arg, "crit"))
  35. return 2;
  36. else if (!strcmp(arg, "ERR") || !strcmp(arg, "err"))
  37. return 3;
  38. else if (!strcmp(arg, "WARN") || !strcmp(arg, "warn"))
  39. return 4;
  40. else if (!strcmp(arg, "NOTICE") || !strcmp(arg, "notice"))
  41. return 5;
  42. else if (!strcmp(arg, "INFO") || !strcmp(arg, "info"))
  43. return 6;
  44. else if (!strcmp(arg, "DEBUG") || !strcmp(arg, "debug"))
  45. return 7;
  46. else {
  47. printf("dmesg: unknown level '%s'\n", arg);
  48. }
  49. return -2;
  50. }
  51. /**
  52. * @brief 打印dmesg手册
  53. */
  54. void print_help_msg() {
  55. const char *help_msg =
  56. "Usage:\n"
  57. " dmesg [options]\n\n"
  58. "Display or control the kernel ring buffer.\n\n"
  59. "Options:\n"
  60. " -C, --clear clear the kernel ring buffer\n"
  61. " -c, --read-clear read and clear all messages\n"
  62. " -l, --level <list> restrict output to defined levels\n"
  63. " -h, --help display this help\n\n"
  64. "Supported log levels (priorities):\n"
  65. " emerg - system is unusable\n"
  66. " alert - action must be taken immediately\n"
  67. " crit - critical conditions\n"
  68. " err - error conditions\n"
  69. " warn - warning conditions\n"
  70. " notice - normal but significant condition\n"
  71. " info - informational\n"
  72. " debug - debug-level messages\n";
  73. printf("%s\n", help_msg);
  74. }
  75. /**
  76. * @brief 打印dmesg错误使用的信息
  77. */
  78. void print_bad_usage_msg() {
  79. const char *bad_usage_msg =
  80. "dmesg: bad usage\nTry 'dmesg --help' for more information.";
  81. printf("%s\n", bad_usage_msg);
  82. }
  83. int main(int argc, char **argv) {
  84. unsigned int len = 1;
  85. char *buf = NULL;
  86. int opt;
  87. unsigned int color = 65280;
  88. // 获取内核缓冲区大小
  89. len = klogctl(10, buf, len);
  90. if (len < 16 * 1024)
  91. len = 16 * 1024;
  92. if (len > 16 * 1024 * 1024)
  93. len = 16 * 1024 * 1024;
  94. buf = malloc(len);
  95. if (buf == NULL) {
  96. perror("");
  97. return -1;
  98. }
  99. if (argc == 1) {
  100. // 无选项参数,默认打印所有日志消息
  101. len = klogctl(2, buf, len);
  102. } else {
  103. // 获取第一个选项参数
  104. opt = getoption(argv[1]);
  105. // 无效参数
  106. if (opt == -1) {
  107. print_bad_usage_msg();
  108. return -1;
  109. }
  110. // 打印帮助手册
  111. else if (opt == 0) {
  112. print_help_msg();
  113. return 0;
  114. }
  115. // 4 -> 读取内核缓冲区后,清空缓冲区
  116. // 5 -> 清空内核缓冲区
  117. else if (opt == 4 || opt == 5) {
  118. len = klogctl(opt, buf, len);
  119. }
  120. // 读取特定日志级别的消息
  121. else if (opt == 8) {
  122. // 无指定日志级别参数,打印错误使用信息
  123. if (argc < 3) {
  124. print_bad_usage_msg();
  125. return -1;
  126. }
  127. int level = -1;
  128. // 获取日志级别
  129. // 这里加1的原因是:如果klogctl的第三个参数是0,不会发生系统调用
  130. level = getlevel(argv[2]) + 1;
  131. if (level == -1)
  132. return -1;
  133. klogctl(8, buf, level);
  134. len = klogctl(2, buf, len);
  135. }
  136. }
  137. // 当前打印内容
  138. // 0: 日志级别
  139. // 1: 时间戳
  140. // 2: 代码行号
  141. // 3: 日志消息
  142. unsigned int content = 0;
  143. for (int i = 0; i < len; i++) {
  144. char c[2];
  145. c[0] = buf[i];
  146. c[1] = '\0';
  147. syscall(100000, &c[0], color, 0);
  148. if (content == 0 && buf[i] == '>') {
  149. content++;
  150. } else if (content == 1 && buf[i] == ']') {
  151. color = 16744448;
  152. content++;
  153. } else if (content == 2 && buf[i] == ')') {
  154. color = 16777215;
  155. content++;
  156. } else if (content == 3 && buf[i] == '\n') {
  157. color = 65280;
  158. content = 0;
  159. }
  160. }
  161. free(buf);
  162. return 0;
  163. }