vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

exec-ulimit.c (5294B)


      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 /* 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. */
     40 #undef RLIM_INFINITY
     41 #define RLIM_INFINITY (~0UL)
     42 #define OLD_RLIM_INFINITY (~0UL>>1)
     43 
     44 #define DECLARE_LIMIT(RES,FNAME) { #FNAME, RLIMIT_##RES }
     45 
     46 int	wrapper_exit_code = 255;
     47 
     48 static struct {
     49     char const	*fname;
     50     int		code;
     51 } const LIMITS[] = {
     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),
     62 };
     63 
     64 static rlim_t
     65 readValue(int fd, char const *filename)
     66 {
     67   char		buf[128];
     68   size_t	len = Eread(fd, buf, sizeof(buf)-1);
     69   long int	res;
     70   char *	errptr;
     71 
     72   buf[len] = '\0';
     73   if (strncmp(buf, "inf", 3)==0) return RLIM_INFINITY;
     74   res = strtol(buf, &errptr, 0);
     75 
     76   if (errptr!=buf) {
     77     switch (*errptr) {
     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;
     82       default	:  break;
     83     }
     84   }
     85 
     86   if (errptr==buf || (*errptr!='\0' && *errptr!='\n')) {
     87     WRITE_MSG(2, "Invalid limit in '");
     88     WRITE_STR(2, filename);
     89     WRITE_STR(2, "'\n");
     90     exit(255);
     91   }
     92 
     93   return res;
     94 }
     95 
     96 static bool
     97 readSingleLimit(struct rlimit *lim, char const *fname_base)
     98 {
     99   size_t	fname_len = strlen(fname_base);
    100   char		fname[fname_len + sizeof(".hard")];
    101   int		fd;
    102   bool		is_modified = false;
    103 
    104   strcpy(fname, fname_base);
    105   
    106   fd = open(fname, O_RDONLY);
    107   if (fd!=-1) {
    108     rlim_t	tmp = readValue(fd, fname_base);
    109     lim->rlim_cur = tmp;
    110     lim->rlim_max = tmp;
    111     Eclose(fd);
    112 
    113     is_modified = true;
    114   }
    115 
    116   strcpy(fname+fname_len, ".hard");
    117   fd = open(fname, O_RDONLY);
    118   if (fd!=-1) {
    119     lim->rlim_max = readValue(fd, fname_base);
    120     Eclose(fd);
    121     
    122     is_modified = true;
    123   }
    124 
    125   strcpy(fname+fname_len, ".soft");
    126   fd = open(fname, O_RDONLY);
    127   if (fd!=-1) {
    128     lim->rlim_cur = readValue(fd, fname_base);
    129     Eclose(fd);
    130     
    131     is_modified = true;
    132   }
    133 
    134   if (is_modified &&
    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;
    139 
    140   return is_modified;
    141 }
    142 
    143 static void
    144 showHelp(int fd, char const *cmd, int res)
    145 {
    146   WRITE_MSG(fd, "Usage:  ");
    147   WRITE_STR(fd, cmd);
    148   WRITE_STR(fd,
    149 	    "<ulimit-cfgdir> <cmd> <argv>*\n\n"
    150 	    "Please report bugs to " PACKAGE_BUGREPORT "\n");
    151   exit(res);
    152 }
    153 
    154 static void
    155 showVersion()
    156 {
    157   WRITE_MSG(1,
    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);
    162   exit(0);
    163 }
    164 
    165 int main(int argc, char *argv[])
    166 {
    167   size_t		i;
    168   int			cur_fd = Eopen(".", O_RDONLY, 0);
    169   bool			in_dir = false;
    170 
    171   if (argc==2) {
    172     if (strcmp(argv[1], "--help")==0)    showHelp(1,argv[0],0);
    173     if (strcmp(argv[1], "--version")==0) showVersion();
    174   }
    175 
    176   if (argc<3) {
    177     WRITE_MSG(2, "Bad parameter count; use '--help' for more information.\n");
    178     exit(255);
    179   }
    180 
    181   if (chdir(argv[1])!=-1) {
    182     in_dir = true;
    183   }
    184   for (i=0; i<sizeof(LIMITS)/sizeof(LIMITS[0]); ++i) {
    185     struct rlimit	limit;
    186 
    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);
    196     }
    197     else {
    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);
    201     }
    202   }
    203   if (in_dir)
    204     Efchdir(cur_fd);
    205   Eclose(cur_fd);
    206 
    207   Eexecv(argv[2], argv+2);
    208 }