3 // Copyright (C) 2005 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
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.
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.
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.
23 #include <lib_internal/util.h>
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>
37 int wrapper_exit_code = EXIT_FAILURE;
40 showFD(int fd_in, int fd_out)
47 len = Eread(fd_in, buf, sizeof(buf));
50 EwriteAll(fd_out, ptr, len);
55 redirectFileInternal(int argc, char *argv[],
56 int mode, bool is_input,
57 char const *operation)
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;
68 fd = EopenD(argv[1], mode, 0644);
69 if (is_input) showFD(fd, 1);
77 testInternal(int argc, char *argv[], char const *operation)
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;
88 if (stat(argv[1], &st)==-1) return -1;
89 else return st.st_mode;
93 execCat(int argc, char *argv[])
95 return redirectFileInternal(argc, argv,
96 O_RDONLY|O_NOCTTY, true,
101 execAppend(int argc, char *argv[])
103 return redirectFileInternal(argc, argv,
104 O_WRONLY|O_CREAT|O_APPEND, false,
109 execTruncate(int argc, char *argv[])
111 return redirectFileInternal(argc, argv,
112 O_WRONLY|O_CREAT|O_TRUNC, false,
117 execRm(int argc, char *argv[])
120 int res = EXIT_SUCCESS;
123 WRITE_MSG(2, "No files specified for 'rm' operation; try '--help' for more information\n");
124 return wrapper_exit_code;
128 if (unlink(argv[i])==-1) {
129 PERROR_Q(ENSC_WRAPPERS_PREFIX "unlink", argv[i]);
138 execTestFile(int argc, char *argv[])
140 int res = testInternal(argc, argv, "testfile");
142 return res!=-1 && S_ISREG(res) ? EXIT_SUCCESS : EXIT_FAILURE;
146 execMkdir(int argc, char *argv[])
149 int res = EXIT_SUCCESS;
152 WRITE_MSG(2, "No files specified for 'mkdir' operation; try '--help' for more information\n");
153 return wrapper_exit_code;
157 if (mkdir(argv[i], 0755)==-1) {
158 PERROR_Q(ENSC_WRAPPERS_PREFIX "mkdir", argv[i]);
167 execChmod(int argc, char *argv[])
170 int res = EXIT_SUCCESS;
174 WRITE_MSG(2, "No files specified for 'chmod' operation; try '--help' for more information\n");
175 return wrapper_exit_code;
178 if (!isNumberUnsigned(argv[1], &mode, 1)) {
179 WRITE_MSG(2, "Invalid mode: '");
180 WRITE_STR(2, argv[1]);
186 if (chmod(argv[i], mode)==-1) {
187 PERROR_Q(ENSC_WRAPPERS_PREFIX "chmod", argv[i]);
196 execLink(int argc, char *argv[])
198 int res = EXIT_SUCCESS;
201 WRITE_MSG(2, "Need exactly two files for 'link' operation; try '--help' for more information\n");
202 return wrapper_exit_code;
205 if (symlink(argv[1], argv[2])==-1) {
206 PERROR_Q(ENSC_WRAPPERS_PREFIX "link", argv[1]);
214 execMv(int argc, char *argv[])
216 int res = EXIT_SUCCESS;
219 WRITE_MSG(2, "Need exactly two files for 'mv' operation; try '--help' for more information\n");
220 return wrapper_exit_code;
223 if (rename(argv[1], argv[2])==-1) {
224 PERROR_Q(ENSC_WRAPPERS_PREFIX "mv", argv[1]);
231 static struct Command {
233 int (*handler)(int argc, char *argv[]);
234 } const COMMANDS[] = {
236 { "append", execAppend },
237 { "truncate", execTruncate },
238 { "testfile", execTestFile },
240 { "mkdir", execMkdir },
241 { "chmod", execChmod },
242 { "link", execLink },
252 " [--] <cmd> <args>*\n\n"
253 "This program chroots into the current directory and executes the specified\n"
254 "commands there. This means that all used paths are relative to the current\n"
255 "directory, and symlinks can point to files under the current path only.\n"
257 "The supported commands are:\n"
258 " cat <file> ... gives out <file> to stdout\n"
259 " append <file> ... appends stdin to <file> which is created when needed\n"
260 " truncate <file> ... clear <file> and fill it with stdin; the <file> is\n"
261 " created when needed\n"
262 " rm <file>+ ... unlink the given files\n"
263 " mkdir <file>+ ... create the given directories\n"
264 " chmod <mode> <file>+\n"
265 " ... change access permissions of files\n"
266 " link <src> <dst> ... create a symbolic link from <src> to <dst>\n"
267 " mv <src> <dst> ... rename <src> to <dst>\n"
268 "\nPlease report bugs to " PACKAGE_BUGREPORT "\n");
276 "chroot-sh " VERSION " -- execute commands within a chroot\n"
277 "This program is part of " PACKAGE_STRING "\n\n"
278 "Copyright (C) 2005 Enrico Scholz\n"
279 VERSION_COPYRIGHT_DISCLAIMER);
284 int main(int argc, char *argv[])
286 struct Command const *cmd;
290 if (strcmp(argv[idx], "--help") ==0) showHelp();
291 if (strcmp(argv[idx], "--version")==0) showVersion();
292 if (strcmp(argv[idx], "--")==0) ++idx;
296 WRITE_MSG(2, "No command specified; try '--help' for more information\n");
297 return wrapper_exit_code;
303 for (cmd=COMMANDS+0; cmd->cmd!=0; ++cmd) {
304 if (strcmp(cmd->cmd, argv[idx])==0)
305 return cmd->handler(argc-idx, argv+idx);
308 WRITE_MSG(2, "Invalid command '");
309 WRITE_STR(2, argv[idx]);
310 WRITE_MSG(2, "'; try '--help' for more information\n");
312 return wrapper_exit_code;