]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/utmp.c
restart the container at reboot
[mirror_lxc.git] / src / lxc / utmp.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <fcntl.h>
30 #include <sys/inotify.h>
31
32 #include "conf.h"
33 #include "cgroup.h"
34 #include "start.h"
35 #include "mainloop.h"
36 #include "lxc.h"
37 #include "log.h"
38 #define __USE_GNU
39 #include <utmpx.h>
40 #undef __USE_GNU
41
42 lxc_log_define(lxc_utmp, lxc);
43
44 static int utmp_handler(int fd, void *data, struct lxc_epoll_descr *descr)
45 {
46 struct inotify_event ie;
47 struct utmpx *utmpx;
48 struct lxc_handler *handler = (struct lxc_handler *)data;
49 struct lxc_conf *conf = handler->conf;
50 char prevrun_level = 'N', currun_level = 'N';
51 int ntasks, ret;
52 char path[MAXPATHLEN];
53
54 if (read(fd, &ie, sizeof(ie)) < 0) {
55 SYSERROR("failed to read utmp notification");
56 return -1;
57 }
58
59 if (snprintf(path, MAXPATHLEN, "%s/var/run/utmp", conf->rootfs) >
60 MAXPATHLEN) {
61 ERROR("path is too long");
62 return -1;
63 }
64
65 if (utmpxname(path)) {
66 SYSERROR("failed to 'utmpxname'");
67 return -1;
68 }
69
70 setutxent();
71
72 while ((utmpx = getutxent())) {
73
74 if (utmpx->ut_type == RUN_LVL) {
75 prevrun_level = utmpx->ut_pid / 256;
76 currun_level = utmpx->ut_pid % 256;
77 }
78 }
79
80 ntasks = lxc_cgroup_nrtasks(handler->name);
81 if (ntasks < 0) {
82 ERROR("failed to get the number of tasks");
83 goto out;
84 }
85
86 if (ntasks == 1 && prevrun_level == '3') {
87
88 DEBUG("run level is %c/%c", prevrun_level, currun_level);
89 DEBUG("there is %d tasks remaining", ntasks);
90
91 if (currun_level == '0') {
92 INFO("container has shutdown");
93 kill(handler->pid, SIGKILL);
94 }
95
96 if (currun_level == '6') {
97 INFO("container has rebooted");
98 conf->reboot = 1;
99 kill(handler->pid, SIGKILL);
100 }
101 }
102
103 ret = 0;
104 out:
105 endutxent();
106
107 return ret;
108 }
109
110 int lxc_utmp_mainloop_add(struct lxc_epoll_descr *descr,
111 struct lxc_handler *handler)
112 {
113 struct lxc_conf *conf = handler->conf;
114 char path[MAXPATHLEN];
115 int fd, wd;
116
117 if (!conf->rootfs)
118 return 0;
119
120 if (snprintf(path, MAXPATHLEN, "%s/var/run/utmp", conf->rootfs) >
121 MAXPATHLEN) {
122 ERROR("path is too long");
123 return -1;
124 }
125
126 if (access(path, F_OK)) {
127 WARN("'%s' not found", path);
128 return 0;
129 }
130
131 fd = inotify_init();
132 if (fd < 0) {
133 SYSERROR("failed to inotify_init");
134 return -1;
135 }
136
137 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
138 SYSERROR("failed to set inotify fd to close-on-exec");
139 close(fd);
140 return -1;
141 }
142
143 wd = inotify_add_watch(fd, path, IN_MODIFY);
144 if (wd < 0) {
145 SYSERROR("failed to add watch for '%s'", path);
146 close(fd);
147 return -1;
148 }
149
150 if (lxc_mainloop_add_handler(descr, fd, utmp_handler, handler)) {
151 SYSERROR("failed to add mainloop");
152 close(fd);
153 return -1;
154 }
155
156 return 0;
157 }