summaryrefslogtreecommitdiff
blob: 1bcd20a01929cf3a9dacbaf91036dc28e5020774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From d3a300383c1973efb37dd4baf3668f0a6a75c9b2 Mon Sep 17 00:00:00 2001
From: Michal Hrusecky <Michal@Hrusecky.net>
Date: Mon, 13 Dec 2010 16:22:37 +0100
Subject: [PATCH] Wildcards substitutions in destinations of rules

Rules can be written using wildcards, but destinations had to be static.
This patch adds support for following strings in destination:

   %u - uid
   %U - username, uid in case of error
   %g - gid
   %G - group name, gid in case of error
   %p - pid
   %P - proccess name, pid in case of error

So more general rules can be specified using wildcards. Example rule can
be:

*@users        *     %G/%U

This will put all users in their own cgroups named by their login and 
group.

Signed-off-by: Michal Hrusecky <Michal@Hrusecky.net>
---
 src/api.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 81 insertions(+), 1 deletions(-)

diff --git a/src/api.c b/src/api.c
index 859190a..29b8627 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2366,6 +2366,12 @@ int cgroup_change_cgroup_flags(uid_t uid, gid_t gid,
 	/* Temporary pointer to a rule */
 	struct cgroup_rule *tmp = NULL;
 
+	/* Temporary variables for destination substitution */
+	char newdest[FILENAME_MAX];
+	int i, j;
+	struct passwd * user_info;
+	struct group  * group_info;
+
 	/* Return codes */
 	int ret = 0;
 
@@ -2418,7 +2424,81 @@ int cgroup_change_cgroup_flags(uid_t uid, gid_t gid,
 	do {
 		cgroup_dbg("Executing rule %s for PID %d... ", tmp->username,
 								pid);
-		ret = cgroup_change_cgroup_path(tmp->destination,
+		// Destination substitutions
+		for(j = i = 0; i < strlen(tmp->destination); i++, j++) {
+			if(tmp->destination[i] == '%') {
+				switch(tmp->destination[++i]) {
+					case 'u':
+						j += snprintf(newdest+j,
+							FILENAME_MAX-j,
+							"%d", uid);
+						i++;
+						break;
+					case 'U':
+						user_info = getpwuid(uid);
+						if(user_info) {
+							j += snprintf(newdest+j,
+								FILENAME_MAX-j,
+								"%s",
+								user_info ->
+								pw_name);
+						} else {
+							j += snprintf(newdest+j,
+								FILENAME_MAX-j,
+								"%d", uid);
+						}
+						i++;
+						break;
+					case 'g':
+						j += snprintf(newdest+j,
+							FILENAME_MAX-j,
+							"%d", gid);
+						i++;
+						break;
+					case 'G':
+						group_info = getgrgid(gid);
+						if(group_info) {
+							j += snprintf(newdest+j,
+								FILENAME_MAX-j,
+								"%s",
+								group_info ->
+								gr_name);
+						} else {
+							j += snprintf(newdest+j,
+								FILENAME_MAX-j,
+								"%d", gid);
+						}
+						i++;
+						break;
+					case 'p':
+						j += snprintf(newdest+j,
+							FILENAME_MAX-j,
+							"%d", pid);
+						i++;
+						break;
+					case 'P':
+						if(procname) {
+							j += snprintf(newdest+j,
+								FILENAME_MAX-j,
+								"%s",
+								procname);
+						} else {
+							j += snprintf(newdest+j,
+								FILENAME_MAX-j,
+								"%d", pid);
+						}
+						i++;
+						break;
+					default:
+						newdest[j++] = '%';
+				}
+			}
+			if(tmp->destination[i] == '\\')
+				i++;
+			newdest[j] = tmp->destination[i];
+		}
+		newdest[j] = 0;
+		ret = cgroup_change_cgroup_path(newdest,
 				pid, (const char * const *)tmp->controllers);
 		if (ret) {
 			cgroup_dbg("FAILED! (Error Code: %d)\n", ret);
-- 
1.7.3.3