3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <sys/resource.h>
31 #define ENSC_WRAPPERS_PREFIX "exec-ulimit: "
32 #define ENSC_WRAPPERS_UNISTD 1
33 #define ENSC_WRAPPERS_FCNTL 1
34 #define ENSC_WRAPPERS_RESOURCE 1
37 /* dietlibc specifies this as (~0UL>>1), which is what's returned from
38 * sys_old_getrlimit, called on some arches for getrlimit.
39 * Reset it here so the kernel will have the correct values when we set it. */
41 #define RLIM_INFINITY (~0UL)
42 #define OLD_RLIM_INFINITY (~0UL>>1)
44 #define DECLARE_LIMIT(RES,FNAME) { #FNAME, RLIMIT_##RES }
46 int wrapper_exit_code = 255;
52 DECLARE_LIMIT(CORE, core),
53 DECLARE_LIMIT(CPU, cpu),
54 DECLARE_LIMIT(DATA, data),
55 DECLARE_LIMIT(FSIZE, fsize),
56 DECLARE_LIMIT(LOCKS, locks),
57 DECLARE_LIMIT(MEMLOCK, memlock),
58 DECLARE_LIMIT(NOFILE, nofile),
59 DECLARE_LIMIT(NPROC, nproc),
60 DECLARE_LIMIT(RSS, rss),
61 DECLARE_LIMIT(STACK, stack),
65 readValue(int fd, char const *filename)
68 size_t len = Eread(fd, buf, sizeof(buf)-1);
73 if (strncmp(buf, "inf", 3)==0) return RLIM_INFINITY;
74 res = strtol(buf, &errptr, 0);
78 case 'M' : res *= 1024; /* fallthrough */
79 case 'K' : res *= 1024; ++errptr; break;
80 case 'm' : res *= 1000; /* fallthrough */
81 case 'k' : res *= 1000; ++errptr; break;
86 if (errptr==buf || (*errptr!='\0' && *errptr!='\n')) {
87 WRITE_MSG(2, "Invalid limit in '");
88 WRITE_STR(2, filename);
97 readSingleLimit(struct rlimit *lim, char const *fname_base)
99 size_t fname_len = strlen(fname_base);
100 char fname[fname_len + sizeof(".hard")];
102 bool is_modified = false;
104 strcpy(fname, fname_base);
106 fd = open(fname, O_RDONLY);
108 rlim_t tmp = readValue(fd, fname_base);
116 strcpy(fname+fname_len, ".hard");
117 fd = open(fname, O_RDONLY);
119 lim->rlim_max = readValue(fd, fname_base);
125 strcpy(fname+fname_len, ".soft");
126 fd = open(fname, O_RDONLY);
128 lim->rlim_cur = readValue(fd, fname_base);
135 lim->rlim_max!=RLIM_INFINITY &&
136 (lim->rlim_cur==RLIM_INFINITY ||
137 lim->rlim_cur>lim->rlim_max))
138 lim->rlim_cur = lim->rlim_max;
144 showHelp(int fd, char const *cmd, int res)
146 WRITE_MSG(fd, "Usage: ");
149 "<ulimit-cfgdir> <cmd> <argv>*\n\n"
150 "Please report bugs to " PACKAGE_BUGREPORT "\n");
158 "exec-ulimit " VERSION " -- executes programs with resource limits\n"
159 "This program is part of " PACKAGE_STRING "\n\n"
160 "Copyright (C) 2003 Enrico Scholz\n"
161 VERSION_COPYRIGHT_DISCLAIMER);
165 int main(int argc, char *argv[])
168 int cur_fd = Eopen(".", O_RDONLY, 0);
172 if (strcmp(argv[1], "--help")==0) showHelp(1,argv[0],0);
173 if (strcmp(argv[1], "--version")==0) showVersion();
177 WRITE_MSG(2, "Bad parameter count; use '--help' for more information.\n");
181 if (chdir(argv[1])!=-1) {
184 for (i=0; i<sizeof(LIMITS)/sizeof(LIMITS[0]); ++i) {
187 Egetrlimit(LIMITS[i].code, &limit);
188 /* if this arch uses sys_old_getrlimit... */
189 if (limit.rlim_cur == OLD_RLIM_INFINITY)
190 limit.rlim_cur = RLIM_INFINITY;
191 if (in_dir && readSingleLimit(&limit, LIMITS[i].fname))
192 Esetrlimit(LIMITS[i].code, &limit);
193 else if (LIMITS[i].code != RLIMIT_NOFILE) {
194 limit.rlim_max = RLIM_INFINITY;
195 Esetrlimit(LIMITS[i].code, &limit);
198 /* RLIMIT_NOFILE can't be set to infinity, 1024*1024 seems to be the limit in most kernels */
199 limit.rlim_max = 1024*1024;
200 setrlimit(LIMITS[i].code, &limit);
207 Eexecv(argv[2], argv+2);