144
static int setup_tty_service(const char *name, int *ttyfd)
147
struct sockaddr_un addr = { 0 };
148
char *offset = &addr.sun_path[1];
150
strcpy(offset, name);
151
addr.sun_path[0] = '\0';
153
fd = lxc_af_unix_open(addr.sun_path, SOCK_STREAM, 0);
157
if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
158
SYSERROR("failed to close-on-exec flag");
168
142
static int sigchld_handler(int fd, void *data,
169
143
struct lxc_epoll_descr *descr)
176
static int ttyclient_handler(int fd, void *data,
177
struct lxc_epoll_descr *descr)
150
int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state)
180
struct lxc_tty_info *tty_info = data;
182
for (i = 0; i < tty_info->nbtty; i++) {
184
if (tty_info->pty_info[i].busy != fd)
187
lxc_mainloop_del_handler(descr, fd);
188
tty_info->pty_info[i].busy = 0;
152
handler->state = state;
153
lxc_monitor_send_state(name, state);
195
static int ttyservice_handler(int fd, void *data,
196
struct lxc_epoll_descr *descr)
198
int conn, ttynum, val = 1, ret = -1;
199
struct lxc_tty_info *tty_info = data;
201
conn = accept(fd, NULL, 0);
203
SYSERROR("failed to accept tty client");
207
if (setsockopt(conn, SOL_SOCKET, SO_PASSCRED, &val, sizeof(val))) {
208
SYSERROR("failed to enable credential on socket");
212
if (lxc_af_unix_rcv_credential(conn, &ttynum, sizeof(ttynum)))
216
if (ttynum > tty_info->nbtty)
219
if (tty_info->pty_info[ttynum - 1].busy)
225
/* fixup index tty1 => [0] */
227
ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy;
230
/* we didn't find any available slot for tty */
231
if (ttynum > tty_info->nbtty)
235
if (lxc_af_unix_send_fd(conn, tty_info->pty_info[ttynum - 1].master,
236
&ttynum, sizeof(ttynum)) < 0) {
237
ERROR("failed to send tty to client");
241
if (lxc_mainloop_add_handler(descr, conn,
242
ttyclient_handler, tty_info)) {
243
ERROR("failed to add tty client handler");
247
tty_info->pty_info[ttynum - 1].busy = conn;
257
157
int lxc_poll(const char *name, struct lxc_handler *handler)
259
159
int sigfd = handler->sigfd;
260
160
int pid = handler->pid;
261
const struct lxc_tty_info *tty_info = &handler->tty_info;
263
int nfds, ttyfd = -1, ret = -1;
264
162
struct lxc_epoll_descr descr;
266
if (tty_info->nbtty && setup_tty_service(name, &ttyfd)) {
267
ERROR("failed to create the tty service point");
164
if (lxc_mainloop_open(&descr)) {
165
ERROR("failed to create mainloop");
271
/* sigfd + nb tty + tty service
272
* if tty is enabled */
273
nfds = tty_info->nbtty + 1 + tty_info->nbtty ? 1 : 0;
275
if (lxc_mainloop_open(nfds, &descr)) {
276
ERROR("failed to create mainloop");
280
169
if (lxc_mainloop_add_handler(&descr, sigfd, sigchld_handler, &pid)) {
281
170
ERROR("failed to add handler for the signal");
282
171
goto out_mainloop_open;
285
if (tty_info->nbtty) {
286
if (lxc_mainloop_add_handler(&descr, ttyfd,
289
ERROR("failed to add handler for the tty");
290
goto out_mainloop_open;
174
if (lxc_command_mainloop_add(name, &descr, handler))
175
goto out_mainloop_open;
294
177
ret = lxc_mainloop(&descr);
299
182
out_mainloop_open:
300
183
lxc_mainloop_close(&descr);
308
static int save_init_pid(const char *name, pid_t pid)
310
char init[MAXPATHLEN];
314
snprintf(init, MAXPATHLEN, LXCPATH "/%s/init", name);
316
if (!asprintf(&val, "%d\n", pid)) {
317
SYSERROR("failed to allocate memory");
321
fd = open(init, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
323
SYSERROR("failed to open '%s'", init);
327
if (write(fd, val, strlen(val)) < 0) {
328
SYSERROR("failed to write the init pid");
342
static void remove_init_pid(const char *name, pid_t pid)
344
char init[MAXPATHLEN];
346
snprintf(init, MAXPATHLEN, LXCPATH "/%s/init", name);
350
189
static int fdname(int fd, char *name, size_t size)
352
191
char path[MAXPATHLEN];
402
241
memset(handler, 0, sizeof(*handler));
404
handler->lock = lxc_get_lock(name);
405
if (handler->lock < 0)
408
243
/* Begin the set the state to STARTING*/
409
if (lxc_setstate(name, STARTING)) {
244
if (lxc_set_state(name, handler, STARTING)) {
410
245
ERROR("failed to set state '%s'", lxc_state2str(STARTING));
414
if (console_init(handler->tty, sizeof(handler->tty))) {
249
if (lxc_conf_init(&handler->conf)) {
250
ERROR("failed to initialize the configuration");
255
if (access(rcfile, F_OK)) {
256
ERROR("failed to access '%s'", rcfile);
260
if (lxc_config_read(rcfile, &handler->conf)) {
261
ERROR("failed to read '%s'", rcfile);
266
if (console_init(handler->conf.console,
267
sizeof(handler->conf.console))) {
415
268
ERROR("failed to initialize the console");
416
269
goto out_aborting;
419
if (lxc_create_tty(name, &handler->tty_info)) {
272
if (lxc_create_tty(name, &handler->conf)) {
420
273
ERROR("failed to create the ttys");
421
274
goto out_aborting;
457
308
/* The STOPPING state is there for future cleanup code
458
309
* which can take awhile
460
lxc_setstate(name, STOPPING);
461
lxc_setstate(name, STOPPED);
311
lxc_set_state(name, handler, STOPPING);
312
lxc_set_state(name, handler, STOPPED);
462
313
lxc_unlink_nsgroup(name);
465
remove_init_pid(name, handler->pid);
466
lxc_delete_tty(&handler->tty_info);
467
lxc_put_lock(handler->lock);
316
lxc_delete_tty(&handler->conf.tty_info);
562
416
clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
563
if (conf_has_network(name))
417
if (!lxc_list_empty(&handler->conf.network)) {
564
419
clone_flags |= CLONE_NEWNET;
421
/* that should be done before the clone because we will
422
* fill the netdev index and use them in the child
424
if (lxc_create_network(&handler->conf.network)) {
425
ERROR("failed to create the network");
566
430
/* Create a process in a new set of namespaces */
567
431
handler->pid = lxc_clone(do_start, &start_arg, clone_flags);
568
432
if (handler->pid < 0) {
581
if (lxc_rename_nsgroup(name, handler->pid) || lxc_link_nsgroup(name))
445
if (lxc_rename_nsgroup(name, handler))
584
448
/* Create the network configuration */
585
if (clone_flags & CLONE_NEWNET &&
586
conf_create_network(name, handler->pid)) {
587
ERROR("failed to create the configured network");
449
if (clone_flags & CLONE_NEWNET) {
450
if (lxc_assign_network(&handler->conf.network, handler->pid)) {
451
ERROR("failed to create the configured network");
591
456
/* Tell the child to continue its initialization */