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