00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "asterisk.h"
00015
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <unistd.h>
00019 #define _XOPEN_SOURCE 600
00020 #include <string.h>
00021 #include <ctype.h>
00022 #include <sys/time.h>
00023 #include <sys/resource.h>
00024 #include <errno.h>
00025 #include "asterisk/module.h"
00026 #include "asterisk/cli.h"
00027
00028 static struct limits {
00029 int resource;
00030 char limit[3];
00031 char desc[40];
00032 } limits[] = {
00033 {
00034 RLIMIT_CPU, "-t", "cpu time"}, {
00035 RLIMIT_FSIZE, "-f", "file size"}, {
00036 RLIMIT_DATA, "-d", "program data segment"}, {
00037 RLIMIT_STACK, "-s", "program stack size"}, {
00038 RLIMIT_CORE, "-c", "core file size"},
00039 #ifdef RLIMIT_RSS
00040 {
00041 RLIMIT_RSS, "-m", "resident memory"}, {
00042 RLIMIT_NPROC, "-u", "number of processes"}, {
00043 RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM"},
00044 #endif
00045 {
00046 RLIMIT_NOFILE, "-n", "number of file descriptors"},
00047 #ifndef RLIMIT_AS
00048 #define RLIMIT_AS RLIMIT_VMEM
00049 #endif
00050 {
00051 RLIMIT_AS, "-v", "virtual memory"},};
00052
00053 static int str2limit(const char *string)
00054 {
00055 size_t i;
00056 for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) {
00057 if (!strcasecmp(string, limits[i].limit))
00058 return limits[i].resource;
00059 }
00060 return -1;
00061 }
00062
00063 static const char *str2desc(const char *string)
00064 {
00065 size_t i;
00066 for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) {
00067 if (!strcmp(string, limits[i].limit))
00068 return limits[i].desc;
00069 }
00070 return "<unknown>";
00071 }
00072
00073 static int my_ulimit(int fd, int argc, char **argv)
00074 {
00075 int resource;
00076 struct rlimit rlimit = { 0, 0 };
00077 if (argc > 3)
00078 return RESULT_SHOWUSAGE;
00079
00080 if (argc == 1) {
00081 char arg2[3];
00082 char *newargv[2] = { "ulimit", arg2 };
00083 for (resource = 0; resource < sizeof(limits) / sizeof(limits[0]); resource++) {
00084 ast_copy_string(arg2, limits[resource].limit, sizeof(arg2));
00085 my_ulimit(fd, 2, newargv);
00086 }
00087 return RESULT_SUCCESS;
00088 } else {
00089 resource = str2limit(argv[1]);
00090 if (resource == -1) {
00091 ast_cli(fd, "Unknown resource\n");
00092 return RESULT_FAILURE;
00093 }
00094
00095 if (argc == 3) {
00096 if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
00097 ast_cli(fd, "Resource not permitted to be set\n");
00098 return RESULT_FAILURE;
00099 }
00100
00101 sscanf(argv[2], "%d", (int *) &rlimit.rlim_cur);
00102 rlimit.rlim_max = rlimit.rlim_cur;
00103 setrlimit(resource, &rlimit);
00104 return RESULT_SUCCESS;
00105 } else {
00106 if (!getrlimit(resource, &rlimit)) {
00107 char printlimit[32];
00108 const char *desc;
00109 if (rlimit.rlim_max == RLIM_INFINITY)
00110 ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
00111 else
00112 snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
00113 desc = str2desc(argv[1]);
00114 ast_cli(fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, argv[1], printlimit);
00115 } else
00116 ast_cli(fd, "Could not retrieve resource limits for %s: %s\n", str2desc(argv[1]), strerror(errno));
00117 return RESULT_SUCCESS;
00118 }
00119 }
00120 }
00121
00122 static char *complete_ulimit(const char *line, const char *word, int pos, int state)
00123 {
00124 int which = 0, i;
00125 int wordlen = strlen(word);
00126
00127 if (pos > 2)
00128 return NULL;
00129 for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) {
00130 if (!strncasecmp(limits[i].limit, word, wordlen)) {
00131 if (++which > state)
00132 return ast_strdup(limits[i].limit);
00133 }
00134 }
00135 return NULL;
00136 }
00137
00138 static char ulimit_usage[] =
00139 "Usage: ulimit {-d|-l|-f|-m|-s|-t|-u|-v|-c|-n} [<num>]\n"
00140 " Shows or sets the corresponding resource limit.\n"
00141 " -d Process data segment [readonly]\n"
00142 " -l Memory lock size [readonly]\n"
00143 " -f File size\n"
00144 " -m Process resident memory [readonly]\n"
00145 " -s Process stack size [readonly]\n"
00146 " -t CPU usage [readonly]\n"
00147 " -u Child processes\n" " -v Process virtual memory [readonly]\n" " -c Core dump file size\n" " -n Number of file descriptors\n";
00148
00149 static struct ast_cli_entry cli_ulimit = {
00150 {"ulimit", NULL}, my_ulimit,
00151 "Set or show process resource limits", ulimit_usage, complete_ulimit
00152 };
00153
00154 static int unload_module(void)
00155 {
00156 return ast_cli_unregister(&cli_ulimit);
00157 }
00158
00159 static int load_module(void)
00160 {
00161 return ast_cli_register(&cli_ulimit) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
00162 }
00163
00164 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");