2 * linux/kernel/vserver/helper.c
4 * Virtual Context Support
6 * Copyright (C) 2004-2005 Herbert Pƶtzl
12 #include <linux/errno.h>
13 #include <linux/kmod.h>
14 #include <linux/sched.h>
15 #include <linux/reboot.h>
16 #include <linux/vs_base.h>
17 #include <linux/vs_context.h>
18 #include <linux/vs_network.h>
19 #include <linux/vserver/signal.h>
21 #include <asm/uaccess.h>
22 #include <asm/unistd.h>
25 char vshelper_path[255] = "/sbin/vshelper";
28 static int do_vshelper(char *name, char *argv[], char *envp[], int sync)
32 if ((ret = call_usermodehelper(name, argv, envp, sync))) {
34 "%s: (%s %s) returned %s with %d\n",
35 name, argv[1], argv[2],
36 sync?"sync":"async", ret);
38 vxdprintk(VXD_CBIT(switch, 4),
39 "%s: (%s %s) returned %s with %d",
40 name, argv[1], argv[2], sync?"sync":"async", ret);
45 * vshelper path is set via /proc/sys
46 * invoked by vserver sys_reboot(), with
47 * the following arguments
49 * argv [0] = vshelper_path;
50 * argv [1] = action: "restart", "halt", "poweroff", ...
51 * argv [2] = context identifier
53 * envp [*] = type-specific parameters
56 long vs_reboot_helper(struct vx_info *vxi, int cmd, void __user *arg)
58 char id_buf[8], cmd_buf[16];
59 char uid_buf[16], pid_buf[16];
62 char *argv[] = {vshelper_path, NULL, id_buf, 0};
63 char *envp[] = {"HOME=/", "TERM=linux",
64 "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
65 uid_buf, pid_buf, cmd_buf, 0};
67 if (vx_info_state(vxi, VXS_HELPER))
69 vxi->vx_state |= VXS_HELPER;
71 snprintf(id_buf, sizeof(id_buf)-1, "%d", vxi->vx_id);
73 snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
74 snprintf(uid_buf, sizeof(uid_buf)-1, "VS_UID=%d", current->uid);
75 snprintf(pid_buf, sizeof(pid_buf)-1, "VS_PID=%d", current->pid);
78 case LINUX_REBOOT_CMD_RESTART:
82 case LINUX_REBOOT_CMD_HALT:
86 case LINUX_REBOOT_CMD_POWER_OFF:
90 case LINUX_REBOOT_CMD_SW_SUSPEND:
95 vxi->vx_state &= ~VXS_HELPER;
99 #ifndef CONFIG_VSERVER_LEGACY
100 ret = do_vshelper(vshelper_path, argv, envp, 1);
102 ret = do_vshelper(vshelper_path, argv, envp, 0);
104 vxi->vx_state &= ~VXS_HELPER;
105 __wakeup_vx_info(vxi);
106 return (ret) ? -EPERM : 0;
110 long vs_reboot(unsigned int cmd, void __user *arg)
112 struct vx_info *vxi = current->vx_info;
115 vxdprintk(VXD_CBIT(misc, 5),
116 "vs_reboot(%p[#%d],%d)",
117 vxi, vxi?vxi->vx_id:0, cmd);
119 ret = vs_reboot_helper(vxi, cmd, arg);
123 vxi->reboot_cmd = cmd;
124 if (vx_info_flags(vxi, VXF_REBOOT_KILL, 0)) {
126 case LINUX_REBOOT_CMD_RESTART:
127 case LINUX_REBOOT_CMD_HALT:
128 case LINUX_REBOOT_CMD_POWER_OFF:
129 vx_info_kill(vxi, 0, SIGKILL);
130 vx_info_kill(vxi, 1, SIGKILL);
140 * argv [0] = vshelper_path;
141 * argv [1] = action: "startup", "shutdown"
142 * argv [2] = context identifier
144 * envp [*] = type-specific parameters
147 long vs_state_change(struct vx_info *vxi, unsigned int cmd)
149 char id_buf[8], cmd_buf[16];
150 char *argv[] = {vshelper_path, NULL, id_buf, 0};
151 char *envp[] = {"HOME=/", "TERM=linux",
152 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", cmd_buf, 0};
154 if (!vx_info_flags(vxi, VXF_SC_HELPER, 0))
157 snprintf(id_buf, sizeof(id_buf)-1, "%d", vxi->vx_id);
158 snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
165 argv[1] = "shutdown";
171 do_vshelper(vshelper_path, argv, envp, 1);
177 * argv [0] = vshelper_path;
178 * argv [1] = action: "netup", "netdown"
179 * argv [2] = context identifier
181 * envp [*] = type-specific parameters
184 long vs_net_change(struct nx_info *nxi, unsigned int cmd)
186 char id_buf[8], cmd_buf[16];
187 char *argv[] = {vshelper_path, NULL, id_buf, 0};
188 char *envp[] = {"HOME=/", "TERM=linux",
189 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", cmd_buf, 0};
191 if (!nx_info_flags(nxi, NXF_SC_HELPER, 0))
194 snprintf(id_buf, sizeof(id_buf)-1, "%d", nxi->nx_id);
195 snprintf(cmd_buf, sizeof(cmd_buf)-1, "VS_CMD=%08x", cmd);
208 do_vshelper(vshelper_path, argv, envp, 1);