res_limit.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Resource limits
  5. *
  6. * Copyright (c) 2006 Tilghman Lesher. All rights reserved.
  7. *
  8. * Tilghman Lesher <res_limit_200607@the-tilghman.com>
  9. *
  10. * This code is released by the author with no restrictions on usage.
  11. *
  12. */
  13. /*! \file
  14. *
  15. * \brief Resource limits
  16. *
  17. * \author Tilghman Lesher <res_limit_200607@the-tilghman.com>
  18. */
  19. /*** MODULEINFO
  20. <support_level>core</support_level>
  21. ***/
  22. #include "asterisk.h"
  23. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  24. #include <ctype.h>
  25. #include <sys/time.h>
  26. #include <sys/resource.h>
  27. #include "asterisk/module.h"
  28. #include "asterisk/cli.h"
  29. /* Find proper rlimit for virtual memory */
  30. #ifdef RLIMIT_AS
  31. #define VMEM_DEF RLIMIT_AS
  32. #else
  33. #ifdef RLIMIT_VMEM
  34. #define VMEM_DEF RLIMIT_VMEM
  35. #endif
  36. #endif
  37. static const struct limits {
  38. int resource;
  39. char limit[3];
  40. char desc[40];
  41. char clicmd[15];
  42. } limits[] = {
  43. { RLIMIT_CPU, "-t", "cpu time", "time" },
  44. { RLIMIT_FSIZE, "-f", "file size" , "file" },
  45. { RLIMIT_DATA, "-d", "program data segment", "data" },
  46. { RLIMIT_STACK, "-s", "program stack size", "stack" },
  47. { RLIMIT_CORE, "-c", "core file size", "core" },
  48. #ifdef RLIMIT_RSS
  49. { RLIMIT_RSS, "-m", "resident memory", "memory" },
  50. { RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM", "locked" },
  51. #endif
  52. #ifdef RLIMIT_NPROC
  53. { RLIMIT_NPROC, "-u", "number of processes", "processes" },
  54. #endif
  55. { RLIMIT_NOFILE, "-n", "number of file descriptors", "descriptors" },
  56. #ifdef VMEM_DEF
  57. { VMEM_DEF, "-v", "virtual memory", "virtual" },
  58. #endif
  59. };
  60. static int str2limit(const char *string)
  61. {
  62. size_t i;
  63. for (i = 0; i < ARRAY_LEN(limits); i++) {
  64. if (!strcasecmp(string, limits[i].clicmd))
  65. return limits[i].resource;
  66. }
  67. return -1;
  68. }
  69. static const char *str2desc(const char *string)
  70. {
  71. size_t i;
  72. for (i = 0; i < ARRAY_LEN(limits); i++) {
  73. if (!strcmp(string, limits[i].clicmd))
  74. return limits[i].desc;
  75. }
  76. return "<unknown>";
  77. }
  78. static char *complete_ulimit(struct ast_cli_args *a)
  79. {
  80. int which = 0, i;
  81. int wordlen = strlen(a->word);
  82. if (a->pos > 1)
  83. return NULL;
  84. for (i = 0; i < ARRAY_LEN(limits); i++) {
  85. if (!strncasecmp(limits[i].clicmd, a->word, wordlen)) {
  86. if (++which > a->n)
  87. return ast_strdup(limits[i].clicmd);
  88. }
  89. }
  90. return NULL;
  91. }
  92. static char *handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  93. {
  94. int resource;
  95. struct rlimit rlimit = { 0, 0 };
  96. switch (cmd) {
  97. case CLI_INIT:
  98. e->command = "ulimit";
  99. e->usage =
  100. "Usage: ulimit {data|"
  101. #ifdef RLIMIT_RSS
  102. "limit|"
  103. #endif
  104. "file|"
  105. #ifdef RLIMIT_RSS
  106. "memory|"
  107. #endif
  108. "stack|time|"
  109. #ifdef RLIMIT_NPROC
  110. "processes|"
  111. #endif
  112. #ifdef VMEM_DEF
  113. "virtual|"
  114. #endif
  115. "core|descriptors} [<num>]\n"
  116. " Shows or sets the corresponding resource limit.\n"
  117. " data Process data segment [readonly]\n"
  118. #ifdef RLIMIT_RSS
  119. " lock Memory lock size [readonly]\n"
  120. #endif
  121. " file File size\n"
  122. #ifdef RLIMIT_RSS
  123. " memory Process resident memory [readonly]\n"
  124. #endif
  125. " stack Process stack size [readonly]\n"
  126. " time CPU usage [readonly]\n"
  127. #ifdef RLIMIT_NPROC
  128. " processes Child processes\n"
  129. #endif
  130. #ifdef VMEM_DEF
  131. " virtual Process virtual memory [readonly]\n"
  132. #endif
  133. " core Core dump file size\n"
  134. " descriptors Number of file descriptors\n";
  135. return NULL;
  136. case CLI_GENERATE:
  137. return complete_ulimit(a);
  138. }
  139. if (a->argc > 3)
  140. return CLI_SHOWUSAGE;
  141. if (a->argc == 1) {
  142. char arg2[15];
  143. const char * const newargv[2] = { "ulimit", arg2 };
  144. for (resource = 0; resource < ARRAY_LEN(limits); resource++) {
  145. struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
  146. ast_copy_string(arg2, limits[resource].clicmd, sizeof(arg2));
  147. handle_cli_ulimit(e, CLI_HANDLER, &newArgs);
  148. }
  149. return CLI_SUCCESS;
  150. } else {
  151. resource = str2limit(a->argv[1]);
  152. if (resource == -1) {
  153. ast_cli(a->fd, "Unknown resource\n");
  154. return CLI_FAILURE;
  155. }
  156. if (a->argc == 3) {
  157. int x;
  158. #ifdef RLIMIT_NPROC
  159. if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
  160. #else
  161. if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
  162. #endif
  163. ast_cli(a->fd, "Resource not permitted to be set\n");
  164. return CLI_FAILURE;
  165. }
  166. sscanf(a->argv[2], "%30d", &x);
  167. rlimit.rlim_max = rlimit.rlim_cur = x;
  168. setrlimit(resource, &rlimit);
  169. return CLI_SUCCESS;
  170. } else {
  171. if (!getrlimit(resource, &rlimit)) {
  172. char printlimit[32];
  173. const char *desc;
  174. if (rlimit.rlim_max == RLIM_INFINITY)
  175. ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
  176. else
  177. snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
  178. desc = str2desc(a->argv[1]);
  179. ast_cli(a->fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, a->argv[1], printlimit);
  180. } else
  181. ast_cli(a->fd, "Could not retrieve resource limits for %s: %s\n", str2desc(a->argv[1]), strerror(errno));
  182. return CLI_SUCCESS;
  183. }
  184. }
  185. }
  186. static struct ast_cli_entry cli_ulimit =
  187. AST_CLI_DEFINE(handle_cli_ulimit, "Set or show process resource limits");
  188. static int unload_module(void)
  189. {
  190. return ast_cli_unregister(&cli_ulimit);
  191. }
  192. static int load_module(void)
  193. {
  194. return ast_cli_register(&cli_ulimit) ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  195. }
  196. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");