uname.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. htop - generic/uname.c
  3. (C) 2021 htop dev team
  4. Released under the GNU GPLv2+, see the COPYING file
  5. in the source distribution for its full text.
  6. */
  7. #include "config.h" // IWYU pragma: keep
  8. #include "generic/uname.h"
  9. #include <stdbool.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include "Macros.h"
  13. #include "XUtils.h"
  14. #ifdef HAVE_SYS_UTSNAME_H
  15. #include <sys/utsname.h>
  16. #endif
  17. #ifndef OSRELEASEFILE
  18. #define OSRELEASEFILE "/etc/os-release"
  19. #endif
  20. static void parseOSRelease(char* buffer, size_t bufferLen) {
  21. FILE* fp = fopen(OSRELEASEFILE, "r");
  22. if (!fp) {
  23. xSnprintf(buffer, bufferLen, "No OS Release");
  24. return;
  25. }
  26. char name[64] = {'\0'};
  27. char version[64] = {'\0'};
  28. char lineBuffer[256];
  29. while (fgets(lineBuffer, sizeof(lineBuffer), fp)) {
  30. if (String_startsWith(lineBuffer, "PRETTY_NAME=\"")) {
  31. const char* start = lineBuffer + strlen("PRETTY_NAME=\"");
  32. const char* stop = strrchr(lineBuffer, '"');
  33. if (!stop || stop <= start)
  34. continue;
  35. String_safeStrncpy(buffer, start, MINIMUM(bufferLen, (size_t)(stop - start + 1)));
  36. fclose(fp);
  37. return;
  38. }
  39. if (String_startsWith(lineBuffer, "NAME=\"")) {
  40. const char* start = lineBuffer + strlen("NAME=\"");
  41. const char* stop = strrchr(lineBuffer, '"');
  42. if (!stop || stop <= start)
  43. continue;
  44. String_safeStrncpy(name, start, MINIMUM(sizeof(name), (size_t)(stop - start + 1)));
  45. continue;
  46. }
  47. if (String_startsWith(lineBuffer, "VERSION=\"")) {
  48. const char* start = lineBuffer + strlen("VERSION=\"");
  49. const char* stop = strrchr(lineBuffer, '"');
  50. if (!stop || stop <= start)
  51. continue;
  52. String_safeStrncpy(version, start, MINIMUM(sizeof(version), (size_t)(stop - start + 1)));
  53. continue;
  54. }
  55. }
  56. fclose(fp);
  57. snprintf(buffer, bufferLen, "%s%s%s", name[0] ? name : "", name[0] && version[0] ? " " : "", version);
  58. }
  59. char* Generic_uname(void) {
  60. static char savedString[
  61. /* uname structure fields - manpages recommend sizeof */
  62. sizeof(((struct utsname*)0)->sysname) +
  63. sizeof(((struct utsname*)0)->release) +
  64. sizeof(((struct utsname*)0)->machine) +
  65. 16/*markup*/ +
  66. 128/*distro*/] = {'\0'};
  67. static bool loaded_data = false;
  68. if (!loaded_data) {
  69. struct utsname uname_info;
  70. int uname_result = uname(&uname_info);
  71. char distro[128];
  72. parseOSRelease(distro, sizeof(distro));
  73. if (uname_result == 0) {
  74. size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine);
  75. if (!String_contains_i(savedString, distro, false) && sizeof(savedString) > written)
  76. snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro);
  77. } else {
  78. snprintf(savedString, sizeof(savedString), "%s", distro);
  79. }
  80. loaded_data = true;
  81. }
  82. return savedString;
  83. }