util.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #define _GNU_SOURCE /* vasprintf() */
  6. #include <stdint.h>
  7. #include <string.h>
  8. #include "util.h"
  9. /** malloc with error support and size_t overflow protection
  10. * \param nmemb number of objects
  11. * \param size size of single object
  12. * \return non null void pointer
  13. */
  14. void*
  15. xmalloc(size_t nmemb, size_t size)
  16. {
  17. void *ret;
  18. if(SIZE_MAX / nmemb < size)
  19. errl(EXIT_FAILURE, "xmalloc(%zu, %zu), "
  20. "size_t overflow detected", nmemb, size);
  21. if((ret = malloc(nmemb * size)) == NULL)
  22. errl(EXIT_FAILURE, "malloc(%zu)", nmemb * size);
  23. return ret;
  24. }
  25. /** calloc with error support
  26. * \param nmemb Number of objects
  27. * \param size size of single object
  28. * \return non null void pointer
  29. */
  30. void*
  31. xcalloc(size_t nmemb, size_t size)
  32. {
  33. void *ret;
  34. if((ret = calloc(nmemb, size)) == NULL)
  35. errl(EXIT_FAILURE, "calloc(%zu * %zu)", nmemb, size);
  36. return ret;
  37. }
  38. /** realloc with error support and size_t overflow check
  39. * \param ptr old pointer
  40. * \param nmemb number of objects
  41. * \param size size of single object
  42. * \return non null void pointer
  43. */
  44. void *
  45. xrealloc(void *ptr, size_t nmemb, size_t size)
  46. {
  47. void *ret;
  48. if(SIZE_MAX / nmemb < size)
  49. err(EXIT_FAILURE, "xrealloc(%p, %zu, %zu), "
  50. "size_t overflow detected", ptr, nmemb, size);
  51. if((ret = realloc(ptr, nmemb * size)) == NULL)
  52. err(EXIT_FAILURE, "realloc(%p, %zu)", ptr, nmemb * size);
  53. return ret;
  54. }
  55. /** asprintf wrapper
  56. * \param strp target string
  57. * \param fmt format
  58. * \return non zero integer
  59. */
  60. int
  61. xasprintf(char **strp, const char *fmt, ...)
  62. {
  63. int ret;
  64. va_list args;
  65. va_start(args, fmt);
  66. ret = vasprintf(strp, fmt, args);
  67. va_end(args);
  68. if (ret == -1)
  69. errl(EXIT_FAILURE, "asprintf(%s)", fmt);
  70. return ret;
  71. }
  72. /** strdup with error support
  73. * \param str char pointer
  74. * \retun non null void pointer
  75. */
  76. char *
  77. xstrdup(const char *str)
  78. {
  79. char *ret = NULL;
  80. if(str == NULL || (ret = strdup(str)) == NULL)
  81. warnxl("strdup(%s)", str);
  82. return ret;
  83. }
  84. /** Execute a system command
  85. * \param cmd Command
  86. * \return child pid
  87. */
  88. pid_t
  89. spawn(const char *format, ...)
  90. {
  91. char *sh = NULL;
  92. char cmd[512];
  93. va_list ap;
  94. pid_t pid;
  95. size_t len;
  96. va_start(ap, format);
  97. len = vsnprintf(cmd, sizeof(cmd), format, ap);
  98. va_end(ap);
  99. if (len >= sizeof(cmd))
  100. {
  101. warnxl("command too long (> 512 bytes)");
  102. return -1;
  103. }
  104. if(!(sh = getenv("SHELL")) || sh[0] != '/')
  105. sh = "/bin/sh";
  106. if(!(pid = fork()))
  107. {
  108. setsid();
  109. if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1)
  110. warnl("execl(sh -c %s)", cmd);
  111. exit(EXIT_FAILURE);
  112. }
  113. else if (pid == -1)
  114. warnl("fork");
  115. return pid;
  116. }
  117. int
  118. parse_args(char *str, char delim, char end, int narg, char *args[])
  119. {
  120. int i = 0;
  121. for(args[0] = str; *str && (*str != end || *(str - 1) == '\\') && i < narg; ++str)
  122. if(*str == delim && i < narg - 1)
  123. {
  124. *str = '\0';
  125. args[++i] = ++str;
  126. }
  127. *str = '\0';
  128. return i;
  129. }
  130. void
  131. uicb_spawn(Uicb cmd)
  132. {
  133. spawn("%s", cmd);
  134. }