![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
res_limit.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * Resource limits 00005 * 00006 * Copyright (c) 2006 Tilghman Lesher. All rights reserved. 00007 * 00008 * Tilghman Lesher <res_limit_200607@the-tilghman.com> 00009 * 00010 * This code is released by the author with no restrictions on usage. 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 /* Find proper rlimit for virtual memory */ 00029 #ifdef RLIMIT_AS 00030 #define VMEM_DEF RLIMIT_AS 00031 #else 00032 #ifdef RLIMIT_VMEM 00033 #define VMEM_DEF RLIMIT_VMEM 00034 #endif 00035 #endif 00036 00037 static struct limits { 00038 int resource; 00039 char limit[3]; 00040 char desc[40]; 00041 } limits[] = { 00042 { RLIMIT_CPU, "-t", "cpu time" }, 00043 { RLIMIT_FSIZE, "-f", "file size" }, 00044 { RLIMIT_DATA, "-d", "program data segment" }, 00045 { RLIMIT_STACK, "-s", "program stack size" }, 00046 { RLIMIT_CORE, "-c", "core file size" }, 00047 #ifdef RLIMIT_RSS 00048 { RLIMIT_RSS, "-m", "resident memory" }, 00049 { RLIMIT_NPROC, "-u", "number of processes" }, 00050 { RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM" }, 00051 #endif 00052 { RLIMIT_NOFILE, "-n", "number of file descriptors" }, 00053 #ifdef VMEM_DEF 00054 { VMEM_DEF, "-v", "virtual memory" }, 00055 #endif 00056 }; 00057 00058 static int str2limit(const char *string) 00059 { 00060 size_t i; 00061 for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) { 00062 if (!strcasecmp(string, limits[i].limit)) 00063 return limits[i].resource; 00064 } 00065 return -1; 00066 } 00067 00068 static const char *str2desc(const char *string) 00069 { 00070 size_t i; 00071 for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) { 00072 if (!strcmp(string, limits[i].limit)) 00073 return limits[i].desc; 00074 } 00075 return "<unknown>"; 00076 } 00077 00078 static int my_ulimit(int fd, int argc, char **argv) 00079 { 00080 int resource; 00081 struct rlimit rlimit = { 0, 0 }; 00082 if (argc > 3) 00083 return RESULT_SHOWUSAGE; 00084 00085 if (argc == 1) { 00086 char arg2[3]; 00087 char *newargv[2] = { "ulimit", arg2 }; 00088 for (resource = 0; resource < sizeof(limits) / sizeof(limits[0]); resource++) { 00089 ast_copy_string(arg2, limits[resource].limit, sizeof(arg2)); 00090 my_ulimit(fd, 2, newargv); 00091 } 00092 return RESULT_SUCCESS; 00093 } else { 00094 resource = str2limit(argv[1]); 00095 if (resource == -1) { 00096 ast_cli(fd, "Unknown resource\n"); 00097 return RESULT_FAILURE; 00098 } 00099 00100 if (argc == 3) { 00101 int x; 00102 if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) { 00103 ast_cli(fd, "Resource not permitted to be set\n"); 00104 return RESULT_FAILURE; 00105 } 00106 00107 sscanf(argv[2], "%d", &x); 00108 rlimit.rlim_max = rlimit.rlim_cur = x; 00109 setrlimit(resource, &rlimit); 00110 return RESULT_SUCCESS; 00111 } else { 00112 if (!getrlimit(resource, &rlimit)) { 00113 char printlimit[32]; 00114 const char *desc; 00115 if (rlimit.rlim_max == RLIM_INFINITY) 00116 ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit)); 00117 else 00118 snprintf(printlimit, sizeof(printlimit), "limited to %d", (int)rlimit.rlim_cur); 00119 desc = str2desc(argv[1]); 00120 ast_cli(fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, argv[1], printlimit); 00121 } else 00122 ast_cli(fd, "Could not retrieve resource limits for %s: %s\n", str2desc(argv[1]), strerror(errno)); 00123 return RESULT_SUCCESS; 00124 } 00125 } 00126 } 00127 00128 static char *complete_ulimit(const char *line, const char *word, int pos, int state) 00129 { 00130 int which = 0, i; 00131 int wordlen = strlen(word); 00132 00133 if (pos > 2) 00134 return NULL; 00135 for (i = 0; i < sizeof(limits) / sizeof(limits[0]); i++) { 00136 if (!strncasecmp(limits[i].limit, word, wordlen)) { 00137 if (++which > state) 00138 return ast_strdup(limits[i].limit); 00139 } 00140 } 00141 return NULL; 00142 } 00143 00144 static const char ulimit_usage[] = 00145 "Usage: ulimit {-d|-l|-f|-m|-s|-t|-u|-v|-c|-n} [<num>]\n" 00146 " Shows or sets the corresponding resource limit.\n" 00147 " -d Process data segment [readonly]\n" 00148 " -l Memory lock size [readonly]\n" 00149 " -f File size\n" 00150 " -m Process resident memory [readonly]\n" 00151 " -s Process stack size [readonly]\n" 00152 " -t CPU usage [readonly]\n" 00153 " -u Child processes\n" 00154 #ifdef VMEM_DEF 00155 " -v Process virtual memory [readonly]\n" 00156 #endif 00157 " -c Core dump file size\n" 00158 " -n Number of file descriptors\n"; 00159 00160 static struct ast_cli_entry cli_ulimit = { 00161 { "ulimit", NULL }, my_ulimit, 00162 "Set or show process resource limits", ulimit_usage, complete_ulimit }; 00163 00164 static int unload_module(void) 00165 { 00166 return ast_cli_unregister(&cli_ulimit); 00167 } 00168 00169 static int load_module(void) 00170 { 00171 return ast_cli_register(&cli_ulimit)? AST_MODULE_LOAD_FAILURE: AST_MODULE_LOAD_SUCCESS; 00172 } 00173 00174 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits"); 00175