vshost-util-vserver

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

chroot-sh.c (8103B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2005 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 <lib_internal/util.h>
     24 
     25 #include <unistd.h>
     26 #include <stdlib.h>
     27 #include <errno.h>
     28 #include <fcntl.h>
     29 #include <sys/stat.h>
     30 
     31 #define ENSC_WRAPPERS_PREFIX	"chroot-sh: "
     32 #define ENSC_WRAPPERS_UNISTD	1
     33 #define ENSC_WRAPPERS_IO	1
     34 #define ENSC_WRAPPERS_FCNTL	1
     35 #include <ensc_wrappers/wrappers.h>
     36 
     37 int	wrapper_exit_code = EXIT_FAILURE;
     38 
     39 static void
     40 showFD(int fd_in, int fd_out)
     41 {
     42   for (;;) {
     43     char		buf[4096];
     44     char const *	ptr=buf;
     45     ssize_t		len;
     46 
     47     len = Eread(fd_in, buf, sizeof(buf));
     48     if (len<=0) break;
     49 
     50     EwriteAll(fd_out, ptr, len);
     51   }
     52 }
     53 
     54 static int
     55 redirectFileInternal(int argc, char *argv[],
     56 		     int mode, bool is_input,
     57 		     char const *operation)
     58 {
     59   int		fd;
     60 
     61   if (argc<2) {
     62     WRITE_MSG(2, "Not enough parameters for '");
     63     WRITE_STR(2, operation);
     64     WRITE_MSG(2, "' operation; use '--help' for more information\n");
     65     return wrapper_exit_code;
     66   }
     67 
     68   fd = EopenD(argv[1], mode, 0644);
     69   if (is_input) showFD(fd,  1);
     70   else          showFD( 0, fd);
     71   Eclose(fd);
     72 
     73   return EXIT_SUCCESS;
     74 }
     75 
     76 static mode_t
     77 testInternal(int argc, char *argv[], char const *operation)
     78 {
     79   struct stat		st;
     80     
     81   if (argc<2) {
     82     WRITE_MSG(2, "Not enough parameters for '");
     83     WRITE_STR(2, operation);
     84     WRITE_MSG(2, "' operation; use '--help' for more information\n");
     85     return wrapper_exit_code;
     86   }
     87 
     88   if (stat(argv[1], &st)==-1) return -1;
     89   else                        return st.st_mode;
     90 }
     91 
     92 static int
     93 execCat(int argc, char *argv[])
     94 {
     95   return redirectFileInternal(argc, argv,
     96 			      O_RDONLY|O_NOCTTY, true,
     97 			      "cat");
     98 }
     99 
    100 static int
    101 execAppend(int argc, char *argv[])
    102 {
    103   return redirectFileInternal(argc, argv,
    104 			      O_WRONLY|O_CREAT|O_APPEND, false,
    105 			      "append");
    106 }
    107 
    108 static int
    109 execTruncate(int argc, char *argv[])
    110 {
    111   return redirectFileInternal(argc, argv,
    112 			      O_WRONLY|O_CREAT|O_TRUNC, false,
    113 			      "truncate");
    114 }
    115 
    116 static int
    117 execRm(int argc, char *argv[])
    118 {
    119   int		i   = 1;
    120   int		res = EXIT_SUCCESS;
    121   
    122   if (argc<2) {
    123     WRITE_MSG(2, "No files specified for 'rm' operation; try '--help' for more information\n");
    124     return wrapper_exit_code;
    125   }
    126 
    127   for (;i<argc; ++i) {
    128     if (unlink(argv[i])==-1) {
    129       PERROR_Q(ENSC_WRAPPERS_PREFIX "unlink", argv[i]);
    130       res = EXIT_FAILURE;
    131     }
    132   }
    133 
    134   return res;
    135 }
    136 
    137 static int
    138 execTestFile(int argc, char *argv[])
    139 {
    140   int		res = testInternal(argc, argv, "testfile");
    141   
    142   return res!=-1 && S_ISREG(res) ? EXIT_SUCCESS : EXIT_FAILURE;
    143 }
    144 
    145 static int
    146 execMkdir(int argc, char *argv[])
    147 {
    148   int		i   = 1;
    149   int		res = EXIT_SUCCESS;
    150   
    151   if (argc<2) {
    152     WRITE_MSG(2, "No files specified for 'mkdir' operation; try '--help' for more information\n");
    153     return wrapper_exit_code;
    154   }
    155 
    156   for (;i<argc; ++i) {
    157     if (mkdir(argv[i], 0755)==-1) {
    158       PERROR_Q(ENSC_WRAPPERS_PREFIX "mkdir", argv[i]);
    159       res = EXIT_FAILURE;
    160     }
    161   }
    162 
    163   return res;
    164 }
    165 
    166 static int
    167 execChmod(int argc, char *argv[])
    168 {
    169   int		i   = 2;
    170   int		res = EXIT_SUCCESS;
    171   unsigned long mode;
    172   
    173   if (argc<3) {
    174     WRITE_MSG(2, "No files specified for 'chmod' operation; try '--help' for more information\n");
    175     return wrapper_exit_code;
    176   }
    177 
    178   if (!isNumberUnsigned(argv[1], &mode, 1)) {
    179     WRITE_MSG(2, "Invalid mode: '");
    180     WRITE_STR(2, argv[1]);
    181     WRITE_MSG(2, "'\n");
    182     return EXIT_FAILURE;
    183   }
    184 
    185   for (;i<argc; ++i) {
    186     if (chmod(argv[i], mode)==-1) {
    187       PERROR_Q(ENSC_WRAPPERS_PREFIX "chmod", argv[i]);
    188       res = EXIT_FAILURE;
    189     }
    190   }
    191 
    192   return res;
    193 }
    194 
    195 static int
    196 execLink(int argc, char *argv[])
    197 {
    198   int		res = EXIT_SUCCESS;
    199 
    200   if (argc!=3) {
    201     WRITE_MSG(2, "Need exactly two files for 'link' operation; try '--help' for more information\n");
    202     return wrapper_exit_code;
    203   }
    204 
    205   if (symlink(argv[1], argv[2])==-1) {
    206     PERROR_Q(ENSC_WRAPPERS_PREFIX "link", argv[1]);
    207     res = EXIT_FAILURE;
    208   }
    209 
    210   return res;
    211 }
    212 
    213 static int
    214 execMv(int argc, char *argv[])
    215 {
    216   int		res = EXIT_SUCCESS;
    217 
    218   if (argc!=3) {
    219     WRITE_MSG(2, "Need exactly two files for 'mv' operation; try '--help' for more information\n");
    220     return wrapper_exit_code;
    221   }
    222 
    223   if (rename(argv[1], argv[2])==-1) {
    224     PERROR_Q(ENSC_WRAPPERS_PREFIX "mv", argv[1]);
    225     res = EXIT_FAILURE;
    226   }
    227 
    228   return res;
    229 }
    230 
    231 static int
    232 execRealpath(int argc, char *argv[])
    233 {
    234   int		res = EXIT_SUCCESS,
    235 		i;
    236 
    237   if (argc < 2) {
    238     WRITE_MSG(2, "Need some files to work on for 'realpath' operation; try '--help' for more information\n");
    239     return wrapper_exit_code;
    240   }
    241 
    242   for (i = 1; i< argc; i++) {
    243     char buf[4096];
    244 
    245     if (realpath(argv[i], buf) == NULL) {
    246       PERROR_Q(ENSC_WRAPPERS_PREFIX "realpath", argv[i]);
    247       res = EXIT_FAILURE;
    248     }
    249     else {
    250       WRITE_STR(1, buf);
    251       WRITE_MSG(1, "\n");
    252     }
    253   }
    254 
    255   return res;
    256 }
    257 
    258 static struct Command {
    259     char const		*cmd;
    260     int			(*handler)(int argc, char *argv[]);
    261 } const		COMMANDS[] = {
    262   { "cat",      execCat },
    263   { "append",   execAppend },
    264   { "truncate", execTruncate },
    265   { "testfile", execTestFile },
    266   { "rm",       execRm },
    267   { "mkdir",    execMkdir },
    268   { "chmod",    execChmod },
    269   { "link",     execLink },
    270   { "mv",       execMv },
    271   { "realpath", execRealpath },
    272   { 0,0 }
    273 };
    274 
    275 static void
    276 showHelp()
    277 {
    278   WRITE_MSG(1,
    279 	    "Usage: chroot-sh "
    280 	    " [--] <cmd> <args>*\n\n"
    281 	    "This program chroots into the current directory and executes the specified\n"
    282 	    "commands there. This means that all used paths are relative to the current\n"
    283 	    "directory, and symlinks can point to files under the current path only.\n"
    284 	    "\n"
    285 	    "The supported commands are:\n"
    286 	    "  cat <file>       ...  gives out <file> to stdout\n"
    287 	    "  append <file>    ...  appends stdin to <file> which is created when needed\n"
    288 	    "  truncate <file>  ...  clear <file> and fill it with stdin; the <file> is\n"
    289 	    "                       created when needed\n"
    290 	    "  rm <file>+       ...  unlink the given files\n"
    291 	    "  mkdir <file>+    ...  create the given directories\n"
    292 	    "  chmod <mode> <file>+\n"
    293 	    "                   ...  change access permissions of files\n"
    294 	    "  link <src> <dst> ...  create a symbolic link from <src> to <dst>\n"
    295 	    "  mv <src> <dst>   ...  rename <src> to <dst>\n"
    296 	    "  realpath <file>+ ...  output real path of each <file>\n"
    297 	    "\nPlease report bugs to " PACKAGE_BUGREPORT "\n");
    298   exit(0);
    299 }
    300 
    301 static void
    302 showVersion()
    303 {
    304   WRITE_MSG(1,
    305 	    "chroot-sh " VERSION " -- execute commands within a chroot\n"
    306 	    "This program is part of " PACKAGE_STRING "\n\n"
    307 	    "Copyright (C) 2005 Enrico Scholz\n"
    308 	    VERSION_COPYRIGHT_DISCLAIMER);
    309   exit(0);
    310 }
    311 
    312 
    313 int main(int argc, char *argv[])
    314 {
    315   struct Command const	*cmd;
    316   int			idx = 1;
    317   
    318   if (argc>=2) {
    319     if (strcmp(argv[idx], "--help")   ==0) showHelp();
    320     if (strcmp(argv[idx], "--version")==0) showVersion();
    321     if (strcmp(argv[idx], "--")==0)        ++idx;
    322   }
    323 
    324   if (argc<idx+1) {
    325     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
    326     return wrapper_exit_code;
    327   }
    328 
    329   Echroot(".");
    330   Echdir("/");
    331 
    332   for (cmd=COMMANDS+0; cmd->cmd!=0; ++cmd) {
    333     if (strcmp(cmd->cmd, argv[idx])==0)
    334       return cmd->handler(argc-idx, argv+idx);
    335   }
    336 
    337   WRITE_MSG(2, "Invalid command '");
    338   WRITE_STR(2, argv[idx]);
    339   WRITE_MSG(2, "'; try '--help' for more information\n");
    340 
    341   return wrapper_exit_code;
    342 }