aboutsummaryrefslogtreecommitdiff
path: root/src/limits.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/limits.c')
-rw-r--r--src/limits.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/src/limits.c b/src/limits.c
new file mode 100644
index 0000000..90d6459
--- /dev/null
+++ b/src/limits.c
@@ -0,0 +1,299 @@
+/* This file is part of Mailfromd.
+ Copyright (C) 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <pies.h>
+
+#define SET_LIMIT_AS 0x0001
+#define SET_LIMIT_CPU 0x0002
+#define SET_LIMIT_DATA 0x0004
+#define SET_LIMIT_FSIZE 0x0008
+#define SET_LIMIT_NPROC 0x0010
+#define SET_LIMIT_CORE 0x0020
+#define SET_LIMIT_MEMLOCK 0x0040
+#define SET_LIMIT_NOFILE 0x0080
+#define SET_LIMIT_RSS 0x0100
+#define SET_LIMIT_STACK 0x0200
+#define SET_LIMIT_LOGINS 0x0400
+#define SET_LIMIT_PRIO 0x0800
+
+struct limits_rec {
+ unsigned set;
+ rlim_t limit_as;
+ rlim_t limit_cpu;
+ rlim_t limit_data;
+ rlim_t limit_fsize;
+ rlim_t limit_nproc;
+ rlim_t limit_core;
+ rlim_t limit_memlock;
+ rlim_t limit_nofile;
+ rlim_t limit_rss;
+ rlim_t limit_stack;
+ int limit_logins;
+ int limit_prio;
+};
+
+int
+do_set_limit (int rlimit, rlim_t limit)
+{
+ struct rlimit rlim;
+
+ MU_DEBUG2 (pies_debug, MU_DEBUG_TRACE1,
+ "Setting limit %d to %lu\n", rlimit, (unsigned long) limit);
+ rlim.rlim_cur = limit;
+ rlim.rlim_max = limit;
+
+ if (setrlimit(rlimit, &rlim))
+ {
+ mu_diag_output (MU_DIAG_NOTICE, _("error setting limit: %s"),
+ mu_strerror (errno));
+ return 1;
+ }
+ return 0;
+}
+
+static int
+set_prio (int prio)
+{
+ MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE2, "Setting priority to %d\n", prio);
+ if (setpriority (PRIO_PROCESS, 0, prio))
+ {
+ mu_diag_output (MU_DIAG_NOTICE, _("error setting priority: %s"),
+ mu_strerror (errno));
+ return 1;
+ }
+ return 0;
+}
+
+/* Counts the number of user logins and check against the limit */
+static int
+check_logins (const char *name, int limit)
+{
+ mu_diag_output (MU_DIAG_NOTICE, _("L limit is not implemented"));
+ return 0;
+}
+
+int
+set_limits (const char *name, struct limits_rec *lrec)
+{
+ int rc = 0;
+
+ if (!lrec)
+ return 0;
+
+ MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE2, "Setting limits for %s\n", name);
+
+#if defined(RLIMIT_AS)
+ if (lrec->set & SET_LIMIT_AS)
+ rc |= do_set_limit(RLIMIT_AS, lrec->limit_as);
+#endif
+#if defined(RLIMIT_CPU)
+ if (lrec->set & SET_LIMIT_CPU)
+ rc |= do_set_limit(RLIMIT_CPU, lrec->limit_cpu);
+#endif
+#if defined(RLIMIT_DATA)
+ if (lrec->set & SET_LIMIT_DATA)
+ rc |= do_set_limit(RLIMIT_DATA, lrec->limit_data);
+#endif
+#if defined(RLIMIT_FSIZE)
+ if (lrec->set & SET_LIMIT_FSIZE)
+ rc |= do_set_limit(RLIMIT_FSIZE, lrec->limit_fsize);
+#endif
+#if defined(RLIMIT_NPROC)
+ if (lrec->set & SET_LIMIT_NPROC)
+ rc |= do_set_limit(RLIMIT_NPROC, lrec->limit_nproc);
+#endif
+#if defined(RLIMIT_CORE)
+ if (lrec->set & SET_LIMIT_CORE)
+ rc |= do_set_limit(RLIMIT_CORE, lrec->limit_core);
+#endif
+#if defined(RLIMIT_MEMLOCK)
+ if (lrec->set & SET_LIMIT_MEMLOCK)
+ rc |= do_set_limit(RLIMIT_MEMLOCK, lrec->limit_memlock);
+#endif
+#if defined(RLIMIT_NOFILE)
+ if (lrec->set & SET_LIMIT_NOFILE)
+ rc |= do_set_limit(RLIMIT_NOFILE, lrec->limit_nofile);
+#endif
+#if defined(RLIMIT_RSS)
+ if (lrec->set & SET_LIMIT_RSS)
+ rc |= do_set_limit(RLIMIT_RSS, lrec->limit_rss);
+#endif
+#if defined(RLIMIT_STACK)
+ if (lrec->set & SET_LIMIT_STACK)
+ rc |= do_set_limit(RLIMIT_STACK, lrec->limit_stack);
+#endif
+ if (lrec->set & SET_LIMIT_LOGINS)
+ rc |= check_logins(name, lrec->limit_logins);
+ if (lrec->set & SET_LIMIT_PRIO)
+ rc |= set_prio(lrec->limit_logins);
+ return rc;
+}
+
+int
+getlimit (char **ptr, rlim_t *rlim, int mul)
+{
+ if (**ptr == '-')
+ {
+ *rlim = RLIM_INFINITY;
+ ++*ptr;
+ }
+ else
+ {
+ unsigned long val;
+
+ val = strtoul (*ptr, ptr, 10);
+ if (val == 0)
+ return 1;
+ *rlim = val * mul;
+ }
+ return 0;
+}
+
+/* Parse limits string and fill appropriate fields in lrec.
+
+ The string consists of _commands_, optionally separated by any amount
+ of whitespace. A command has the following form:
+
+ [AaCcDdFfMmNnRrSsTtUuLlPp](-|[0-9]+)
+
+ i.e. a letter followed by number or a dash. The latters stands for
+ 'unlimited'. Commands are interpreted as follows:
+
+ Command ulimit setrlimit() The limit it sets
+ option arg
+ -------------------------------------------------------------
+ [Aa] a RLIMIT_AS max address space (KB)
+ [Cc] c RLIMIT_CORE max core file size (KB)
+ [Dd] d RLIMIT_DATA max data size (KB)
+ [Ff] f RLIMIT_FSIZE Maximum filesize (KB)
+ [Mm] m RLIMIT_MEMLOCK max locked-in-memory address
+ space (KB)
+ [Nn] n RLIMIT_NOFILE max number of open files
+ [Rr] r RLIMIT_RSS max resident set size (KB)
+ [Ss] s RLIMIT_STACK max stack size (KB)
+ [Tt] t RLIMIT_CPU max CPU time (MIN)
+ [Uu] u RLIMIT_NPROC max number of processes
+ [Ll] l (none) max number of logins (N/A)
+ [Pp] p (none) process priority -20..20
+ (negative = high priority)
+ */
+int
+parse_limits (limits_record_t *plrec, char *str, char **endp)
+{
+ int c;
+ struct limits_rec *lrec = xmalloc (sizeof (*lrec));
+ *plrec = lrec;
+ lrec->set = 0;
+ while ((c = *str++))
+ {
+ if (c == ' ' || c == '\t')
+ continue;
+ switch (c)
+ {
+ case 'a':
+ case 'A':
+ /* RLIMIT_AS - max address space (KB) */
+ if (!getlimit (&str, &lrec->limit_as, 1024))
+ lrec->set |= SET_LIMIT_AS;
+ break;
+
+ case 't':
+ case 'T':
+ /* RLIMIT_CPU - max CPU time (MIN) */
+ if (!getlimit (&str, &lrec->limit_cpu, 60))
+ lrec->set |= SET_LIMIT_CPU;
+ break;
+
+ case 'd':
+ case 'D':
+ /* RLIMIT_DATA - max data size (KB) */
+ if (!getlimit (&str, &lrec->limit_data, 1024))
+ lrec->set |= SET_LIMIT_DATA;
+ break;
+
+ case 'f':
+ case 'F':
+ /* RLIMIT_FSIZE - Maximum filesize (KB) */
+ if (!getlimit (&str, &lrec->limit_fsize, 1024))
+ lrec->set |= SET_LIMIT_FSIZE;
+ break;
+
+ case 'u':
+ case 'U':
+ /* RLIMIT_NPROC - max number of processes */
+ if (!getlimit (&str, &lrec->limit_nproc, 1))
+ lrec->set |= SET_LIMIT_NPROC;
+ break;
+
+ case 'c':
+ case 'C':
+ /* RLIMIT_CORE - max core file size (KB) */
+ if (!getlimit (&str, &lrec->limit_core, 1024))
+ lrec->set |= SET_LIMIT_CORE;
+ break;
+
+ case 'm':
+ case 'M':
+ /* RLIMIT_MEMLOCK - max locked-in-memory
+ * address space (KB)
+ */
+ if (!getlimit (&str, &lrec->limit_memlock, 1024))
+ lrec->set |= SET_LIMIT_MEMLOCK;
+ break;
+
+ case 'n':
+ case 'N':
+ /* RLIMIT_NOFILE - max number of open files */
+ if (!getlimit (&str, &lrec->limit_nofile, 1))
+ lrec->set |= SET_LIMIT_NOFILE;
+ break;
+
+ case 'r':
+ case 'R':
+ /* RLIMIT_RSS - max resident set size (KB) */
+ if (!getlimit (&str, &lrec->limit_rss, 1024))
+ lrec->set |= SET_LIMIT_RSS;
+ break;
+
+ case 's':
+ case 'S':
+ /* RLIMIT_STACK - max stack size (KB) */
+ if (!getlimit (&str, &lrec->limit_stack, 1024))
+ lrec->set |= SET_LIMIT_STACK;
+ break;
+
+ case 'l':
+ case 'L':
+ lrec->limit_logins = strtol (str, &str, 10);
+ if (lrec->limit_logins >= 0)
+ lrec->set |= SET_LIMIT_LOGINS;
+ break;
+
+ case 'p':
+ case 'P':
+ lrec->limit_prio = strtol (str, &str, 10);
+ if (lrec->limit_prio > 0)
+ lrec->set |= SET_LIMIT_PRIO;
+ break;
+
+ default:
+ *endp = str-1;
+ return 1;
+ }
+ }
+ return 0;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.