extremely small and simple HTTP GET/HEAD-only web server for static content
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.
 
 
 

166 lines
2.8 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. struct server s;
  17. static void
  18. verr(const char *fmt, va_list ap)
  19. {
  20. if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
  21. fprintf(stderr, "%s: ", argv0);
  22. }
  23. vfprintf(stderr, fmt, ap);
  24. if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
  25. fputc(' ', stderr);
  26. perror(NULL);
  27. } else {
  28. fputc('\n', stderr);
  29. }
  30. }
  31. void
  32. warn(const char *fmt, ...)
  33. {
  34. va_list ap;
  35. va_start(ap, fmt);
  36. verr(fmt, ap);
  37. va_end(ap);
  38. }
  39. void
  40. die(const char *fmt, ...)
  41. {
  42. va_list ap;
  43. va_start(ap, fmt);
  44. verr(fmt, ap);
  45. va_end(ap);
  46. exit(1);
  47. }
  48. void
  49. epledge(const char *promises, const char *execpromises)
  50. {
  51. (void)promises;
  52. (void)execpromises;
  53. #ifdef __OpenBSD__
  54. if (pledge(promises, execpromises) == -1) {
  55. die("pledge:");
  56. }
  57. #endif /* __OpenBSD__ */
  58. }
  59. void
  60. eunveil(const char *path, const char *permissions)
  61. {
  62. (void)path;
  63. (void)permissions;
  64. #ifdef __OpenBSD__
  65. if (unveil(path, permissions) == -1) {
  66. die("unveil:");
  67. }
  68. #endif /* __OpenBSD__ */
  69. }
  70. char *
  71. timestamp(time_t t, char buf[TIMESTAMP_LEN])
  72. {
  73. strftime(buf, TIMESTAMP_LEN, "%a, %d %b %Y %T GMT", gmtime(&t));
  74. return buf;
  75. }
  76. int
  77. esnprintf(char *str, size_t size, const char *fmt, ...)
  78. {
  79. va_list ap;
  80. int ret;
  81. va_start(ap, fmt);
  82. ret = vsnprintf(str, size, fmt, ap);
  83. va_end(ap);
  84. return (ret < 0 || (size_t)ret >= size);
  85. }
  86. #define INVALID 1
  87. #define TOOSMALL 2
  88. #define TOOLARGE 3
  89. long long
  90. strtonum(const char *numstr, long long minval, long long maxval,
  91. const char **errstrp)
  92. {
  93. long long ll = 0;
  94. int error = 0;
  95. char *ep;
  96. struct errval {
  97. const char *errstr;
  98. int err;
  99. } ev[4] = {
  100. { NULL, 0 },
  101. { "invalid", EINVAL },
  102. { "too small", ERANGE },
  103. { "too large", ERANGE },
  104. };
  105. ev[0].err = errno;
  106. errno = 0;
  107. if (minval > maxval) {
  108. error = INVALID;
  109. } else {
  110. ll = strtoll(numstr, &ep, 10);
  111. if (numstr == ep || *ep != '\0')
  112. error = INVALID;
  113. else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
  114. error = TOOSMALL;
  115. else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
  116. error = TOOLARGE;
  117. }
  118. if (errstrp != NULL)
  119. *errstrp = ev[error].errstr;
  120. errno = ev[error].err;
  121. if (error)
  122. ll = 0;
  123. return ll;
  124. }
  125. /*
  126. * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
  127. * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
  128. */
  129. #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
  130. void *
  131. reallocarray(void *optr, size_t nmemb, size_t size)
  132. {
  133. if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
  134. nmemb > 0 && SIZE_MAX / nmemb < size) {
  135. errno = ENOMEM;
  136. return NULL;
  137. }
  138. return realloc(optr, size * nmemb);
  139. }