argv_split.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Helper function for splitting a string into an argv-like array.
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/ctype.h>
  6. #include <linux/string.h>
  7. #include <linux/slab.h>
  8. #include <linux/export.h>
  9. static int count_argc(const char *str)
  10. {
  11. int count = 0;
  12. bool was_space;
  13. for (was_space = true; *str; str++) {
  14. if (isspace(*str)) {
  15. was_space = true;
  16. } else if (was_space) {
  17. was_space = false;
  18. count++;
  19. }
  20. }
  21. return count;
  22. }
  23. /**
  24. * argv_free - free an argv
  25. * @argv - the argument vector to be freed
  26. *
  27. * Frees an argv and the strings it points to.
  28. */
  29. void argv_free(char **argv)
  30. {
  31. argv--;
  32. kfree(argv[0]);
  33. kfree(argv);
  34. }
  35. EXPORT_SYMBOL(argv_free);
  36. /**
  37. * argv_split - split a string at whitespace, returning an argv
  38. * @gfp: the GFP mask used to allocate memory
  39. * @str: the string to be split
  40. * @argcp: returned argument count
  41. *
  42. * Returns an array of pointers to strings which are split out from
  43. * @str. This is performed by strictly splitting on white-space; no
  44. * quote processing is performed. Multiple whitespace characters are
  45. * considered to be a single argument separator. The returned array
  46. * is always NULL-terminated. Returns NULL on memory allocation
  47. * failure.
  48. *
  49. * The source string at `str' may be undergoing concurrent alteration via
  50. * userspace sysctl activity (at least). The argv_split() implementation
  51. * attempts to handle this gracefully by taking a local copy to work on.
  52. */
  53. char **argv_split(gfp_t gfp, const char *str, int *argcp)
  54. {
  55. char *argv_str;
  56. bool was_space;
  57. char **argv, **argv_ret;
  58. int argc;
  59. argv_str = kstrndup(str, KMALLOC_MAX_SIZE - 1, gfp);
  60. if (!argv_str)
  61. return NULL;
  62. argc = count_argc(argv_str);
  63. argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
  64. if (!argv) {
  65. kfree(argv_str);
  66. return NULL;
  67. }
  68. *argv = argv_str;
  69. argv_ret = ++argv;
  70. for (was_space = true; *argv_str; argv_str++) {
  71. if (isspace(*argv_str)) {
  72. was_space = true;
  73. *argv_str = 0;
  74. } else if (was_space) {
  75. was_space = false;
  76. *argv++ = argv_str;
  77. }
  78. }
  79. *argv = NULL;
  80. if (argcp)
  81. *argcp = argc;
  82. return argv_ret;
  83. }
  84. EXPORT_SYMBOL(argv_split);