Asterisk - The Open Source Telephony Project  GIT-master-1b41629
res_limit.c
Go to the documentation of this file.
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 
14 /*! \file
15  *
16  * \brief Resource limits
17  *
18  * \author Tilghman Lesher <res_limit_200607@the-tilghman.com>
19  */
20 
21 /*** MODULEINFO
22  <support_level>core</support_level>
23  ***/
24 
25 #include "asterisk.h"
26 
27 #include <ctype.h>
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #include "asterisk/module.h"
31 #include "asterisk/cli.h"
32 
33 /* Find proper rlimit for virtual memory */
34 #ifdef RLIMIT_AS
35 #define VMEM_DEF RLIMIT_AS
36 #else
37 #ifdef RLIMIT_VMEM
38 #define VMEM_DEF RLIMIT_VMEM
39 #endif
40 #endif
41 
42 static const struct limits {
43  int resource;
44  char limit[3];
45  char desc[40];
46  char clicmd[15];
47 } limits[] = {
48  { RLIMIT_CPU, "-t", "cpu time", "time" },
49  { RLIMIT_FSIZE, "-f", "file size" , "file" },
50  { RLIMIT_DATA, "-d", "program data segment", "data" },
51  { RLIMIT_STACK, "-s", "program stack size", "stack" },
52  { RLIMIT_CORE, "-c", "core file size", "core" },
53 #ifdef RLIMIT_RSS
54  { RLIMIT_RSS, "-m", "resident memory", "memory" },
55  { RLIMIT_MEMLOCK, "-l", "amount of memory locked into RAM", "locked" },
56 #endif
57 #ifdef RLIMIT_NPROC
58  { RLIMIT_NPROC, "-u", "number of processes", "processes" },
59 #endif
60  { RLIMIT_NOFILE, "-n", "number of file descriptors", "descriptors" },
61 #ifdef VMEM_DEF
62  { VMEM_DEF, "-v", "virtual memory", "virtual" },
63 #endif
64 };
65 
66 static int str2limit(const char *string)
67 {
68  size_t i;
69  for (i = 0; i < ARRAY_LEN(limits); i++) {
70  if (!strcasecmp(string, limits[i].clicmd))
71  return limits[i].resource;
72  }
73  return -1;
74 }
75 
76 static const char *str2desc(const char *string)
77 {
78  size_t i;
79  for (i = 0; i < ARRAY_LEN(limits); i++) {
80  if (!strcmp(string, limits[i].clicmd))
81  return limits[i].desc;
82  }
83  return "<unknown>";
84 }
85 
86 static char *complete_ulimit(struct ast_cli_args *a)
87 {
88  int which = 0, i;
89  int wordlen = strlen(a->word);
90 
91  if (a->pos > 1)
92  return NULL;
93  for (i = 0; i < ARRAY_LEN(limits); i++) {
94  if (!strncasecmp(limits[i].clicmd, a->word, wordlen)) {
95  if (++which > a->n)
96  return ast_strdup(limits[i].clicmd);
97  }
98  }
99  return NULL;
100 }
101 
102 static char *handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
103 {
104  int resource;
105  struct rlimit rlimit = { 0, 0 };
106 
107  switch (cmd) {
108  case CLI_INIT:
109  e->command = "ulimit";
110  e->usage =
111  "Usage: ulimit {data|"
112 #ifdef RLIMIT_RSS
113  "limit|"
114 #endif
115  "file|"
116 #ifdef RLIMIT_RSS
117  "memory|"
118 #endif
119  "stack|time|"
120 #ifdef RLIMIT_NPROC
121  "processes|"
122 #endif
123 #ifdef VMEM_DEF
124  "virtual|"
125 #endif
126  "core|descriptors} [<num>]\n"
127  " Shows or sets the corresponding resource limit.\n"
128  " data Process data segment [readonly]\n"
129 #ifdef RLIMIT_RSS
130  " lock Memory lock size [readonly]\n"
131 #endif
132  " file File size\n"
133 #ifdef RLIMIT_RSS
134  " memory Process resident memory [readonly]\n"
135 #endif
136  " stack Process stack size [readonly]\n"
137  " time CPU usage [readonly]\n"
138 #ifdef RLIMIT_NPROC
139  " processes Child processes\n"
140 #endif
141 #ifdef VMEM_DEF
142  " virtual Process virtual memory [readonly]\n"
143 #endif
144  " core Core dump file size\n"
145  " descriptors Number of file descriptors\n";
146  return NULL;
147  case CLI_GENERATE:
148  return complete_ulimit(a);
149  }
150 
151  if (a->argc > 3)
152  return CLI_SHOWUSAGE;
153 
154  if (a->argc == 1) {
155  char arg2[15];
156  const char * const newargv[2] = { "ulimit", arg2 };
157  for (resource = 0; resource < ARRAY_LEN(limits); resource++) {
158  struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
159  ast_copy_string(arg2, limits[resource].clicmd, sizeof(arg2));
160  handle_cli_ulimit(e, CLI_HANDLER, &newArgs);
161  }
162  return CLI_SUCCESS;
163  } else {
164  resource = str2limit(a->argv[1]);
165  if (resource == -1) {
166  ast_cli(a->fd, "Unknown resource\n");
167  return CLI_FAILURE;
168  }
169 
170  if (a->argc == 3) {
171  int x;
172 #ifdef RLIMIT_NPROC
173  if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_NPROC && resource != RLIMIT_FSIZE) {
174 #else
175  if (resource != RLIMIT_NOFILE && resource != RLIMIT_CORE && resource != RLIMIT_FSIZE) {
176 #endif
177  ast_cli(a->fd, "Resource not permitted to be set\n");
178  return CLI_FAILURE;
179  }
180 
181  sscanf(a->argv[2], "%30d", &x);
182  rlimit.rlim_max = rlimit.rlim_cur = x;
183  setrlimit(resource, &rlimit);
184  return CLI_SUCCESS;
185  } else {
186  if (!getrlimit(resource, &rlimit)) {
187  char printlimit[32];
188  const char *desc;
189  if (rlimit.rlim_max == RLIM_INFINITY)
190  ast_copy_string(printlimit, "effectively unlimited", sizeof(printlimit));
191  else
192  snprintf(printlimit, sizeof(printlimit), "limited to %d", (int) rlimit.rlim_cur);
193  desc = str2desc(a->argv[1]);
194  ast_cli(a->fd, "%c%s (%s) is %s.\n", toupper(desc[0]), desc + 1, a->argv[1], printlimit);
195  } else
196  ast_cli(a->fd, "Could not retrieve resource limits for %s: %s\n", str2desc(a->argv[1]), strerror(errno));
197  return CLI_SUCCESS;
198  }
199  }
200 }
201 
202 static struct ast_cli_entry cli_ulimit =
203  AST_CLI_DEFINE(handle_cli_ulimit, "Set or show process resource limits");
204 
205 static int unload_module(void)
206 {
207  return ast_cli_unregister(&cli_ulimit);
208 }
209 
210 static int load_module(void)
211 {
213 }
214 
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int resource
Definition: res_limit.c:43
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: main/cli.c:2397
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
Definition: cli.h:152
static struct ast_cli_entry cli_ulimit
Definition: res_limit.c:202
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static int unload_module(void)
Definition: res_limit.c:205
#define ast_cli_register(e)
Registers a command or an array of commands.
Definition: cli.h:256
static const char * str2desc(const char *string)
Definition: res_limit.c:76
static int str2limit(const char *string)
Definition: res_limit.c:66
char clicmd[15]
Definition: res_limit.c:46
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
static char * handle_cli_ulimit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_limit.c:102
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
int errno
char limit[3]
Definition: res_limit.c:44
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static char * complete_ulimit(struct ast_cli_args *a)
Definition: res_limit.c:86
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char desc[40]
Definition: res_limit.c:45
const int pos
Definition: cli.h:164
static int load_module(void)
Definition: res_limit.c:210
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static struct test_val a