do not do the lo-check anymore
[util-vserver.git] / util-vserver / src / exec-ulimit.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
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.
8 //  
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.
13 //  
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.
17
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "util.h"
24
25 #include <sys/time.h>
26 #include <sys/resource.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30
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
35 #include <wrappers.h>
36
37 #define DECLARE_LIMIT(RES,FNAME) { #FNAME, RLIMIT_##RES }
38
39 int     wrapper_exit_code = 255;
40
41 static struct {
42     char const  *fname;
43     int         code;
44 } const LIMITS[] = {
45   DECLARE_LIMIT(CPU,     cpu),
46   DECLARE_LIMIT(DATA,    data),
47   DECLARE_LIMIT(FSIZE,   fsize),
48   DECLARE_LIMIT(LOCKS,   locks),
49   DECLARE_LIMIT(MEMLOCK, memlock),
50   DECLARE_LIMIT(NOFILE,  nofile),
51   DECLARE_LIMIT(NPROC,   nproc),
52   DECLARE_LIMIT(RSS,     rss),
53   DECLARE_LIMIT(STACK,   stack),
54 };
55
56 static rlim_t
57 readValue(int fd, char const *filename)
58 {
59   char          buf[128];
60   size_t        len = Eread(fd, buf, sizeof(buf)-1);
61   long int      res;
62   char *        errptr;
63
64   buf[len] = '\0';
65   if (strncmp(buf, "inf", 3)==0) return RLIM_INFINITY;
66   res = strtol(buf, &errptr, 0);
67
68   if (errptr!=buf) {
69     switch (*errptr) {
70       case 'M'  :  res *= 1024; /* fallthrough */
71       case 'K'  :  res *= 1024; ++errptr; break;
72       case 'm'  :  res *= 1000; /* fallthrough */
73       case 'k'  :  res *= 1000; ++errptr; break;
74       default   :  break;
75     }
76   }
77
78   if (errptr==buf || (*errptr!='\0' && *errptr!='\n')) {
79     WRITE_MSG(2, "Invalid limit in '");
80     WRITE_STR(2, filename);
81     WRITE_STR(2, "'\n");
82     exit(255);
83   }
84
85   return res;
86 }
87
88 static bool
89 readSingleLimit(struct rlimit *lim, char const *fname_base)
90 {
91   size_t        fname_len = strlen(fname_base);
92   char          fname[fname_len + sizeof(".hard")];
93   int           fd;
94   bool          is_modified = false;
95
96   strcpy(fname, fname_base);
97   
98   fd = open(fname, O_RDONLY);
99   if (fd!=-1) {
100     rlim_t      tmp = readValue(fd, fname_base);
101     lim->rlim_cur = tmp;
102     lim->rlim_max = tmp;
103     Eclose(fd);
104
105     is_modified = true;
106   }
107
108   strcpy(fname+fname_len, ".hard");
109   fd = open(fname, O_RDONLY);
110   if (fd!=-1) {
111     lim->rlim_max = readValue(fd, fname_base);
112     Eclose(fd);
113     
114     is_modified = true;
115   }
116
117   strcpy(fname+fname_len, ".soft");
118   fd = open(fname, O_RDONLY);
119   if (fd!=-1) {
120     lim->rlim_cur = readValue(fd, fname_base);
121     Eclose(fd);
122     
123     is_modified = true;
124   }
125
126   if (is_modified &&
127       lim->rlim_max!=RLIM_INFINITY &&
128       (lim->rlim_cur==RLIM_INFINITY ||
129        lim->rlim_cur>lim->rlim_max))
130     lim->rlim_cur = lim->rlim_max;
131
132   return is_modified;
133 }
134
135 static void
136 showHelp(int fd, char const *cmd, int res)
137 {
138   WRITE_MSG(fd, "Usage:  ");
139   WRITE_STR(fd, cmd);
140   WRITE_STR(fd,
141             "<ulimit-cfgdir> <cmd> <argv>*\n\n"
142             "Please report bugs to " PACKAGE_BUGREPORT "\n");
143   exit(res);
144 }
145
146 static void
147 showVersion()
148 {
149   WRITE_MSG(1,
150             "exec-ulimit " VERSION " -- executes programs with resource limits\n"
151             "This program is part of " PACKAGE_STRING "\n\n"
152             "Copyright (C) 2003 Enrico Scholz\n"
153             VERSION_COPYRIGHT_DISCLAIMER);
154   exit(0);
155 }
156
157 int main(int argc, char *argv[])
158 {
159   size_t                i;
160   int                   cur_fd = Eopen(".", O_RDONLY, 0);
161
162   if (argc==2) {
163     if (strcmp(argv[1], "--help")==0)    showHelp(1,argv[0],0);
164     if (strcmp(argv[1], "--version")==0) showVersion();
165   }
166
167   if (argc<3) {
168     WRITE_MSG(2, "Bad parameter count; use '--help' for more information.\n");
169     exit(255);
170   }
171
172   if (chdir(argv[1])!=-1) {
173     for (i=0; i<sizeof(LIMITS)/sizeof(LIMITS[0]); ++i) {
174       struct rlimit     limit;
175
176       Egetrlimit(LIMITS[i].code, &limit);
177       if (readSingleLimit(&limit, LIMITS[i].fname))
178         Esetrlimit(LIMITS[i].code, &limit);
179     }
180     Efchdir(cur_fd);
181   }
182   Eclose(cur_fd);
183
184   Eexecv(argv[2], argv+2);
185 }