Setting tag util-vserver-pl-0.4-29
[util-vserver-pl.git] / src / vsh.c
1 /* Version 2 of vsh. Basically a wrapper around 'vserver <slice name> enter.' */
2
3 #include <unistd.h>
4 #include <pwd.h>
5 #include <string.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <errno.h>
11
12 #define VSH_PATH    "/usr/sbin/vsh"
13 #ifndef PATH_MAX
14 #define PATH_MAX    4096
15 #endif
16
17 #define VSERVER_PATH  "/usr/sbin/vserver"
18
19 char* get_current_username (unsigned int uid)
20 {
21     struct passwd *passwd_entry;
22     if ((passwd_entry = getpwuid(uid)) == NULL) {
23         fprintf(stderr, "Could not look up user record for %d\n", uid);
24         return NULL; 
25     }
26
27     return (strdup(passwd_entry->pw_name));
28 }
29
30 char **extend_argv(int argc, char **argv, int num_extra_args) {
31     int argc2, i;
32     char **argv2;
33
34     argc2 = argc + num_extra_args;
35     argv2 = (char **) malloc((argc2 + 1) * sizeof(char *));
36
37     if (!argv2)
38         return (char **) NULL;
39
40     for (i=0; i<argc; i++) {
41         argv2[i+num_extra_args]=strdup(argv[i]); 
42     }
43     argv2[argc2]=NULL;
44
45     return argv2;
46 }
47
48 void associate_vserver_cgroup(char *slice_name, int pid)
49 {
50     char cgroup_dir[4096], fn[4096];
51     struct stat st;
52     int result;
53     FILE *f;
54
55     sprintf(cgroup_dir, "/dev/cgroup/%s", slice_name);
56
57     result = stat(cgroup_dir, &st);
58     if (result != 0) {
59         // doesn't exist
60         return;
61     }
62
63     if (!S_ISDIR(st.st_mode)) {
64         // not a directory
65         return;
66     }
67
68     /* Write the pid to the cgroup tasks file, so the SSH process is associated
69      * with the correct cgroup
70      */
71
72     sprintf(fn, "%s/tasks", cgroup_dir);
73     f = fopen(fn, "wt");
74     if (f==NULL) {
75         // failed to open
76         return;
77     }
78
79     fprintf(f, "%d\n", pid);
80     fclose(f);
81 }
82
83 #define NUM_VSERVER_EXEC_ARGS 5
84
85 int main(int argc, char **argv, char **envp)
86 {
87     char *slice_name;
88     char **argv2;
89     int argc2;
90     char slice_id_str[256];
91     unsigned int slice_xid;
92
93     slice_xid = getuid();
94     slice_name = get_current_username(slice_xid);
95     if (!slice_name) {
96         fprintf(stderr,"Could not look up slice name\n");
97         goto out_exception;
98     }
99
100     associate_vserver_cgroup(slice_name, getpid());
101     
102     argv2 = extend_argv(argc, argv, NUM_VSERVER_EXEC_ARGS);
103     if (!argv2) goto out_exception;
104         
105     
106     // Populate arguments
107     snprintf(slice_id_str, 255, "%u", slice_xid);
108     argv2[0] = strdup(VSERVER_PATH);
109     argv2[1] = strdup(slice_name);
110     argv2[2] = strdup("exec");
111     argv2[3] = strdup("/bin/su"); 
112     argv2[4] = strdup("-"); 
113     argv2[5] = strdup(slice_name);
114
115     if (setuid(geteuid())) goto out_exception;
116
117     execve(VSERVER_PATH, argv2, envp);
118
119 out_exception:
120     printf("%s\n", strerror(errno));
121     return errno;
122 }