replaced all the small chroot-* programs with a single 'chroot-sh'
[util-vserver.git] / util-vserver / src / chroot-sh.c
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
30 #define ENSC_WRAPPERS_PREFIX    "chroot-sh"
31 #define ENSC_WRAPPERS_UNISTD    1
32 #define ENSC_WRAPPERS_IO        1
33 #define ENSC_WRAPPERS_FCNTL     1
34 #include <ensc_wrappers/wrappers.h>
35
36 int     wrapper_exit_code = EXIT_FAILURE;
37
38 static void
39 showFD(int fd_in, int fd_out)
40 {
41   for (;;) {
42     char                buf[4096];
43     char const *        ptr=buf;
44     ssize_t             len;
45
46     len = Eread(fd_in, buf, sizeof(buf));
47     if (len<=0) break;
48
49     EwriteAll(fd_out, ptr, len);
50   }
51 }
52
53 static int
54 redirectFileInternal(int argc, char *argv[],
55                      int mode, bool is_input,
56                      char const *operation)
57 {
58   int           fd;
59
60   if (argc<2) {
61     WRITE_MSG(2, "Not enough parameters for '");
62     WRITE_STR(2, operation);
63     WRITE_MSG(2, "' operation; use '--help' for more information\n");
64     return wrapper_exit_code;
65   }
66
67   fd = EopenD(argv[1], mode, 0644);
68   if (is_input) showFD(fd,  1);
69   else          showFD( 0, fd);
70   Eclose(fd);
71
72   return EXIT_SUCCESS;
73 }
74
75 static int
76 execCat(int argc, char *argv[])
77 {
78   return redirectFileInternal(argc, argv,
79                               O_RDONLY|O_NOCTTY, true,
80                               "cat");
81 }
82
83 static int
84 execAppend(int argc, char *argv[])
85 {
86   return redirectFileInternal(argc, argv,
87                               O_WRONLY|O_CREAT|O_APPEND, false,
88                               "append");
89 }
90
91 static int
92 execTruncate(int argc, char *argv[])
93 {
94   return redirectFileInternal(argc, argv,
95                               O_WRONLY|O_CREAT|O_TRUNC, false,
96                               "truncate");
97 }
98
99 static int
100 execRm(int argc, char *argv[])
101 {
102   int           i   = 1;
103   int           res = EXIT_SUCCESS;
104   
105   if (argc<2) {
106     WRITE_MSG(2, "No files specified for 'rm' operation; try '--help' for more information\n");
107     return wrapper_exit_code;
108   }
109
110   for (;i<argc; ++i) {
111     if (unlink(argv[i])==-1) {
112       PERROR_Q(ENSC_WRAPPERS_PREFIX "unlink", argv[i]);
113       res = EXIT_FAILURE;
114     }
115   }
116
117   return res;
118 }
119
120 static struct Command {
121     char const          *cmd;
122     int                 (*handler)(int argc, char *argv[]);
123 } const         COMMANDS[] = {
124   { "cat",      execCat },
125   { "append",   execAppend },
126   { "truncate", execTruncate },
127   { "rm",       execRm },
128   { 0,0 }
129 };
130
131 static void
132 showHelp()
133 {
134   WRITE_MSG(1,
135             "Usage: chroot-sh "
136             " [--] <cmd> <args>*\n\n"
137             "This program chroots into the current directory and executes the specified\n"
138             "commands there. This means that all used paths are relative to the current\n"
139             "directory, and symlinks can point to files under the current path only.\n"
140             "\n"
141             "The supported commands are:\n"
142             "  cat <file>      ...  gives out <file> to stdout\n"
143             "  append <file>   ...  appends stdin to <file> which is created when needed\n"
144             "  truncate <file> ...  clear <file> and fill it with stdin; the <file> is\n"
145             "                       created when needed\n"
146             "  rm <file>+      ...  unlink the given files\n\n"
147             "Please report bugs to " PACKAGE_BUGREPORT "\n");
148   exit(0);
149 }
150
151 static void
152 showVersion()
153 {
154   WRITE_MSG(1,
155             "chroot-sh " VERSION " -- execute commands within a chroot\n"
156             "This program is part of " PACKAGE_STRING "\n\n"
157             "Copyright (C) 2005 Enrico Scholz\n"
158             VERSION_COPYRIGHT_DISCLAIMER);
159   exit(0);
160 }
161
162
163 int main(int argc, char *argv[])
164 {
165   struct Command const  *cmd;
166   int                   idx = 1;
167   
168   if (argc>=2) {
169     if (strcmp(argv[idx], "--help")   ==0) showHelp();
170     if (strcmp(argv[idx], "--version")==0) showVersion();
171     if (strcmp(argv[idx], "--")==0)        ++idx;
172   }
173
174   if (argc<idx+1) {
175     WRITE_MSG(2, "No command specified; try '--help' for more information\n");
176     return wrapper_exit_code;
177   }
178
179   Echroot(".");
180   Echdir("/");
181
182   for (cmd=COMMANDS+0; cmd->cmd!=0; ++cmd) {
183     if (strcmp(cmd->cmd, argv[idx])==0)
184       return cmd->handler(argc-idx, argv+idx);
185   }
186
187   WRITE_MSG(2, "Invalid command '");
188   WRITE_STR(2, argv[idx]);
189   WRITE_MSG(2, "'; try '--help' for more information\n");
190
191   return wrapper_exit_code;
192 }