kcmdline.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. *
  6. * kcmdline - Parse /proc/cmdline usefully.
  7. *
  8. * Parses /proc/cmdline and provides an interface for querying
  9. * whether an argument was present, and its value if applicable.
  10. *
  11. * Also converts ASCII field separators to spaces so that cmdline
  12. * arguments can have spaces in them.
  13. *
  14. * Useful for shell scripts.
  15. *
  16. * TODO: This should probably be a library we can use in other
  17. * applications...
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <toaru/hashmap.h>
  24. hashmap_t * args_map = NULL;
  25. int tokenize(char * str, char * sep, char **buf) {
  26. char * pch_i;
  27. char * save_i;
  28. int argc = 0;
  29. pch_i = strtok_r(str,sep,&save_i);
  30. if (!pch_i) { return 0; }
  31. while (pch_i != NULL) {
  32. buf[argc] = (char *)pch_i;
  33. ++argc;
  34. pch_i = strtok_r(NULL,sep,&save_i);
  35. }
  36. buf[argc] = NULL;
  37. return argc;
  38. }
  39. void args_parse(char * _arg) {
  40. char * arg = strdup(_arg);
  41. char * argv[1024];
  42. int argc = tokenize(arg, " ", argv);
  43. for (int i = 0; i < argc; ++i) {
  44. char * c = strdup(argv[i]);
  45. char * name;
  46. char * value;
  47. name = c;
  48. value = NULL;
  49. /* Find the first = and replace it with a null */
  50. char * v = c;
  51. while (*v) {
  52. if (*v == '=') {
  53. *v = '\0';
  54. v++;
  55. value = v;
  56. char * tmp = value;
  57. /* scan it for \037 and replace with spaces */
  58. while (*tmp) {
  59. if (*tmp == '\037') {
  60. *tmp = ' ';
  61. }
  62. tmp++;
  63. }
  64. goto _break;
  65. }
  66. v++;
  67. }
  68. _break:
  69. hashmap_set(args_map, name, value);
  70. }
  71. free(arg);
  72. }
  73. void show_usage(int argc, char * argv[]) {
  74. printf(
  75. "kcmdline - query the kernel command line\n"
  76. "\n"
  77. "usage: %s -g ARG...\n"
  78. " %s -q ARG...\n"
  79. "\n"
  80. " -g \033[3mprint the value for the requested argument\033[0m\n"
  81. " -q \033[3mquery whether the requested argument is present (0 = yes)\033[0m\n"
  82. " -? \033[3mshow this help text\033[0m\n"
  83. "\n", argv[0], argv[0]);
  84. }
  85. int main(int argc, char * argv[]) {
  86. /* Open */
  87. FILE * f = fopen("/proc/cmdline", "r");
  88. if (!f) return 1;
  89. /* Read */
  90. char * cmdline = malloc(4096); /* cmdline can't be longer than that */
  91. memset(cmdline, 0, 4096);
  92. size_t size = fread(cmdline, 1, 4096, f);
  93. if (cmdline[size-1] == '\n') cmdline[size-1] = '\0';
  94. fclose(f);
  95. /* Parse */
  96. args_map = hashmap_create(10);
  97. args_parse(cmdline);
  98. /* Figure out what we're doing */
  99. int opt;
  100. while ((opt = getopt(argc, argv, "?g:q:s")) != -1) {
  101. switch (opt) {
  102. case 'g':
  103. if (hashmap_has(args_map, optarg)) {
  104. char * tmp = (char*)hashmap_get(args_map, optarg);
  105. if (!tmp) {
  106. printf("%s\n", optarg); /* special case = present but not set should yield name of variable */
  107. } else {
  108. printf("%s\n", tmp);
  109. }
  110. return 0;
  111. } else {
  112. return 1;
  113. }
  114. case 'q':
  115. return !hashmap_has(args_map,optarg);
  116. case 's':
  117. return size;
  118. case '?':
  119. show_usage(argc, argv);
  120. return 1;
  121. }
  122. }
  123. fprintf(stdout, "%s\n", cmdline);
  124. }