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