1 |
/* Set a file's translator. |
/* Set a file's translator. |
2 |
|
|
3 |
Copyright (C) 1995,96,97,98,2001 Free Software Foundation, Inc. |
Copyright (C) 1995,96,97,98,2001,02 Free Software Foundation, Inc. |
4 |
|
Written by Miles Bader <miles@gnu.org> |
|
Written by Miles Bader <miles@gnu.ai.mit.edu> |
|
5 |
|
|
6 |
This program is free software; you can redistribute it and/or |
This program is free software; you can redistribute it and/or |
7 |
modify it under the terms of the GNU General Public License as |
modify it under the terms of the GNU General Public License as |
22 |
#include <stdlib.h> |
#include <stdlib.h> |
23 |
#include <string.h> |
#include <string.h> |
24 |
#include <argp.h> |
#include <argp.h> |
25 |
|
#include <error.h> |
26 |
#include <fcntl.h> |
#include <fcntl.h> |
27 |
#include <unistd.h> |
#include <unistd.h> |
28 |
|
|
32 |
#include <hurd/process.h> |
#include <hurd/process.h> |
33 |
#include <version.h> |
#include <version.h> |
34 |
|
|
35 |
|
#include <hurd/lookup.h> |
36 |
|
#include <hurd/fsys.h> |
37 |
|
|
38 |
|
|
39 |
const char *argp_program_version = STANDARD_HURD_VERSION (settrans); |
const char *argp_program_version = STANDARD_HURD_VERSION (settrans); |
40 |
|
|
41 |
#define DEFAULT_TIMEOUT 60 |
#define DEFAULT_TIMEOUT 60 |
54 |
{"timeout", 't',"SEC",0, "Timeout for translator startup, in seconds" |
{"timeout", 't',"SEC",0, "Timeout for translator startup, in seconds" |
55 |
" (default " STRINGIFY (DEFAULT_TIMEOUT) "); 0 means no timeout"}, |
" (default " STRINGIFY (DEFAULT_TIMEOUT) "); 0 means no timeout"}, |
56 |
{"exclusive", 'x', 0, 0, "Only set the translator if there is not one already"}, |
{"exclusive", 'x', 0, 0, "Only set the translator if there is not one already"}, |
57 |
{"orphan", 'o', 0, 0, "Disconnect the translator from the filesystem " |
{"orphan", 'o', 0, 0, "Disconnect old translator from the filesystem " |
58 |
"(do not ask it to go away)"}, |
"(do not ask it to go away)"}, |
59 |
|
|
60 |
|
{"chroot", 'C', 0, 0, |
61 |
|
"Instead of setting the node's translator, take following arguments up to" |
62 |
|
" `--' and run that command chroot'd to the translated node."}, |
63 |
|
|
64 |
{0,0,0,0, "When setting the passive translator, if there's an active translator:"}, |
{0,0,0,0, "When setting the passive translator, if there's an active translator:"}, |
65 |
{"goaway", 'g', 0, 0, "Ask the active translator to go away"}, |
{"goaway", 'g', 0, 0, "Ask the active translator to go away"}, |
66 |
{"keep-active", 'k', 0, 0, "Leave any existing active translator running"}, |
{"keep-active", 'k', 0, 0, "Leave any existing active translator running"}, |
106 |
orphan = 0; |
orphan = 0; |
107 |
int excl = 0; |
int excl = 0; |
108 |
int timeout = DEFAULT_TIMEOUT * 1000; /* ms */ |
int timeout = DEFAULT_TIMEOUT * 1000; /* ms */ |
109 |
|
char **chroot_command = 0; |
110 |
|
|
111 |
/* Parse our options... */ |
/* Parse our options... */ |
112 |
error_t parse_opt (int key, char *arg, struct argp_state *state) |
error_t parse_opt (int key, char *arg, struct argp_state *state) |
138 |
case 'P': pause = 1; break; |
case 'P': pause = 1; break; |
139 |
case 'o': orphan = 1; break; |
case 'o': orphan = 1; break; |
140 |
|
|
141 |
|
case 'C': |
142 |
|
if (chroot_command) |
143 |
|
{ |
144 |
|
argp_error (state, "--chroot given twice"); |
145 |
|
return EINVAL; |
146 |
|
} |
147 |
|
chroot_command = &state->argv[state->next]; |
148 |
|
while (state->next < state->argc) |
149 |
|
{ |
150 |
|
if (!strcmp (state->argv[state->next], "--")) |
151 |
|
{ |
152 |
|
state->argv[state->next++] = 0; |
153 |
|
if (chroot_command[0] == 0) |
154 |
|
{ |
155 |
|
argp_error (state, |
156 |
|
"--chroot must be followed by a command"); |
157 |
|
return EINVAL; |
158 |
|
} |
159 |
|
break; |
160 |
|
} |
161 |
|
++state->next; |
162 |
|
} |
163 |
|
argp_error (state, "--chroot command must be terminated with `--'"); |
164 |
|
return EINVAL; |
165 |
|
|
166 |
case 'c': lookup_flags |= O_CREAT; break; |
case 'c': lookup_flags |= O_CREAT; break; |
167 |
case 'L': lookup_flags &= ~O_NOTRANS; break; |
case 'L': lookup_flags &= ~O_NOTRANS; break; |
168 |
|
|
182 |
|
|
183 |
argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); |
argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); |
184 |
|
|
185 |
if (!active && !passive) |
if (!active && !passive && !chroot_command) |
186 |
passive = 1; /* By default, set the passive translator. */ |
passive = 1; /* By default, set the passive translator. */ |
187 |
|
|
188 |
if (passive) |
if (passive) |
202 |
active_flags = FS_TRANS_SET | FS_TRANS_EXCL; |
active_flags = FS_TRANS_SET | FS_TRANS_EXCL; |
203 |
} |
} |
204 |
|
|
205 |
if (active && argz_len > 0) |
if ((active || chroot_command) && argz_len > 0) |
206 |
{ |
{ |
207 |
/* Error during file lookup; we use this to avoid duplicating error |
/* Error during file lookup; we use this to avoid duplicating error |
208 |
messages. */ |
messages. */ |
216 |
{ |
{ |
217 |
if (pause) |
if (pause) |
218 |
{ |
{ |
219 |
fprintf (stderr, "Translator pid: %d\nPausing...", |
fprintf (stderr, "Translator pid: %d\nPausing...", |
220 |
task2pid (task)); |
task2pid (task)); |
221 |
getchar (); |
getchar (); |
222 |
} |
} |
247 |
error(1, errno, "%s", node_name); |
error(1, errno, "%s", node_name); |
248 |
} |
} |
249 |
|
|
250 |
err = |
if (active || passive) |
251 |
file_set_translator(node, |
{ |
252 |
passive_flags, active_flags, goaway_flags, |
err = file_set_translator (node, |
253 |
argz, argz_len, |
passive_flags, active_flags, goaway_flags, |
254 |
active_control, MACH_MSG_TYPE_COPY_SEND); |
argz, argz_len, |
255 |
if (err) |
active_control, MACH_MSG_TYPE_COPY_SEND); |
256 |
error(5, err, "%s", node_name); |
if (err) |
257 |
|
error (5, err, "%s", node_name); |
258 |
|
} |
259 |
|
|
260 |
|
if (chroot_command) |
261 |
|
{ |
262 |
|
/* We will act as the parent filesystem would for a lookup |
263 |
|
of the active translator's root node, then use this port |
264 |
|
as our root directory while we exec the command. */ |
265 |
|
|
266 |
|
char retry_name[1024]; /* XXX */ |
267 |
|
retry_type do_retry; |
268 |
|
mach_port_t root; |
269 |
|
err = fsys_getroot (active_control, |
270 |
|
MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND, |
271 |
|
NULL, 0, NULL, 0, 0, &do_retry, retry_name, &root); |
272 |
|
mach_port_deallocate (mach_task_self (), active_control); |
273 |
|
if (err) |
274 |
|
error (6, err, "fsys_getroot"); |
275 |
|
err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0, |
276 |
|
do_retry, retry_name, 0, 0, |
277 |
|
&root); |
278 |
|
if (err) |
279 |
|
error (6, err, "cannot resolve root port"); |
280 |
|
|
281 |
|
if (setcrdir (root)) |
282 |
|
error (7, errno, "cannot install root port"); |
283 |
|
mach_port_deallocate (mach_task_self (), root); |
284 |
|
if (chdir ("/")) |
285 |
|
error (8, errno, "cannot chdir to new root"); |
286 |
|
|
287 |
|
execvp (chroot_command[0], chroot_command); |
288 |
|
error (8, errno, "cannot execute %s", chroot_command[0]); |
289 |
|
} |
290 |
|
|
291 |
return 0; |
return 0; |
292 |
} |
} |