Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
4.7 KiB

  1. /* See LICENSE file for copyright and license details. */
  2. #include <errno.h>
  3. #include <limits.h>
  4. #include <stdarg.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <time.h>
  11. #ifdef __OpenBSD__
  12. #include <unistd.h>
  13. #endif /* __OpenBSD__ */
  14. #include "util.h"
  15. char *argv0;
  16. static void
  17. verr(const char *fmt, va_list ap)
  18. {
  19. if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
  20. fprintf(stderr, "%s: ", argv0);
  21. }
  22. vfprintf(stderr, fmt, ap);
  23. if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
  24. fputc(' ', stderr);
  25. perror(NULL);
  26. } else {
  27. fputc('\n', stderr);
  28. }
  29. }
  30. void
  31. warn(const char *fmt, ...)
  32. {
  33. va_list ap;
  34. va_start(ap, fmt);
  35. verr(fmt, ap);
  36. va_end(ap);
  37. }
  38. void
  39. die(const char *fmt, ...)
  40. {
  41. va_list ap;
  42. va_start(ap, fmt);
  43. verr(fmt, ap);
  44. va_end(ap);
  45. exit(1);
  46. }
  47. void
  48. epledge(const char *promises, const char *execpromises)
  49. {
  50. (void)promises;
  51. (void)execpromises;
  52. #ifdef __OpenBSD__
  53. if (pledge(promises, execpromises) == -1) {
  54. die("pledge:");
  55. }
  56. #endif /* __OpenBSD__ */
  57. }
  58. void
  59. eunveil(const char *path, const char *permissions)
  60. {
  61. (void)path;
  62. (void)permissions;
  63. #ifdef __OpenBSD__
  64. if (unveil(path, permissions) == -1) {
  65. die("unveil:");
  66. }
  67. #endif /* __OpenBSD__ */
  68. }
  69. int
  70. timestamp(char *buf, size_t len, time_t t)
  71. {
  72. struct tm tm;
  73. if (gmtime_r(&t, &tm) == NULL ||
  74. strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) {
  75. return 1;
  76. }
  77. return 0;
  78. }
  79. int
  80. esnprintf(char *str, size_t size, const char *fmt, ...)
  81. {
  82. va_list ap;
  83. int ret;
  84. va_start(ap, fmt);
  85. ret = vsnprintf(str, size, fmt, ap);
  86. va_end(ap);
  87. return (ret < 0 || (size_t)ret >= size);
  88. }
  89. int
  90. prepend(char *str, size_t size, const char *prefix)
  91. {
  92. size_t len = strlen(str), prefixlen = strlen(prefix);
  93. if (len + prefixlen + 1 > size) {
  94. return 1;
  95. }
  96. memmove(str + prefixlen, str, len + 1);
  97. memcpy(str, prefix, prefixlen);
  98. return 0;
  99. }
  100. int
  101. spacetok(const char *s, char **t, size_t tlen)
  102. {
  103. const char *tok;
  104. size_t i, j, toki, spaces;
  105. /* fill token-array with NULL-pointers */
  106. for (i = 0; i < tlen; i++) {
  107. t[i] = NULL;
  108. }
  109. toki = 0;
  110. /* don't allow NULL string or leading spaces */
  111. if (!s || *s == ' ') {
  112. return 1;
  113. }
  114. start:
  115. /* skip spaces */
  116. for (; *s == ' '; s++)
  117. ;
  118. /* don't allow trailing spaces */
  119. if (*s == '\0') {
  120. goto err;
  121. }
  122. /* consume token */
  123. for (tok = s, spaces = 0; ; s++) {
  124. if (*s == '\\' && *(s + 1) == ' ') {
  125. spaces++;
  126. s++;
  127. continue;
  128. } else if (*s == ' ') {
  129. /* end of token */
  130. goto token;
  131. } else if (*s == '\0') {
  132. /* end of string */
  133. goto token;
  134. }
  135. }
  136. token:
  137. if (toki >= tlen) {
  138. goto err;
  139. }
  140. if (!(t[toki] = malloc(s - tok - spaces + 1))) {
  141. die("malloc:");
  142. }
  143. for (i = 0, j = 0; j < s - tok - spaces + 1; i++, j++) {
  144. if (tok[i] == '\\' && tok[i + 1] == ' ') {
  145. i++;
  146. }
  147. t[toki][j] = tok[i];
  148. }
  149. t[toki][s - tok - spaces] = '\0';
  150. toki++;
  151. if (*s == ' ') {
  152. s++;
  153. goto start;
  154. }
  155. return 0;
  156. err:
  157. for (i = 0; i < tlen; i++) {
  158. free(t[i]);
  159. t[i] = NULL;
  160. }
  161. return 1;
  162. }
  163. #define INVALID 1
  164. #define TOOSMALL 2
  165. #define TOOLARGE 3
  166. long long
  167. strtonum(const char *numstr, long long minval, long long maxval,
  168. const char **errstrp)
  169. {
  170. long long ll = 0;
  171. int error = 0;
  172. char *ep;
  173. struct errval {
  174. const char *errstr;
  175. int err;
  176. } ev[4] = {
  177. { NULL, 0 },
  178. { "invalid", EINVAL },
  179. { "too small", ERANGE },
  180. { "too large", ERANGE },
  181. };
  182. ev[0].err = errno;
  183. errno = 0;
  184. if (minval > maxval) {
  185. error = INVALID;
  186. } else {
  187. ll = strtoll(numstr, &ep, 10);
  188. if (numstr == ep || *ep != '\0')
  189. error = INVALID;
  190. else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
  191. error = TOOSMALL;
  192. else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
  193. error = TOOLARGE;
  194. }
  195. if (errstrp != NULL)
  196. *errstrp = ev[error].errstr;
  197. errno = ev[error].err;
  198. if (error)
  199. ll = 0;
  200. return ll;
  201. }
  202. /*
  203. * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
  204. * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
  205. */
  206. #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
  207. void *
  208. reallocarray(void *optr, size_t nmemb, size_t size)
  209. {
  210. if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
  211. nmemb > 0 && SIZE_MAX / nmemb < size) {
  212. errno = ENOMEM;
  213. return NULL;
  214. }
  215. return realloc(optr, size * nmemb);
  216. }
  217. int
  218. buffer_appendf(struct buffer *buf, const char *suffixfmt, ...)
  219. {
  220. va_list ap;
  221. int ret;
  222. va_start(ap, suffixfmt);
  223. ret = vsnprintf(buf->data + buf->len,
  224. sizeof(buf->data) - buf->len, suffixfmt, ap);
  225. va_end(ap);
  226. if (ret < 0 || (size_t)ret >= (sizeof(buf->data) - buf->len)) {
  227. /* truncation occured, discard and error out */
  228. memset(buf->data + buf->len, 0,
  229. sizeof(buf->data) - buf->len);
  230. return 1;
  231. }
  232. /* increase buffer length by number of bytes written */
  233. buf->len += ret;
  234. return 0;
  235. }