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 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 <mic...@hrusecky.net> Acked-by: Dhaval Giani <dhaval.gi...@gmail.com> --- doc/man/cgrules.conf.5 | 11 +++++- src/api.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/doc/man/cgrules.conf.5 b/doc/man/cgrules.conf.5 index 4ca6937..9a8a0a3 100644 --- a/doc/man/cgrules.conf.5 +++ b/doc/man/cgrules.conf.5 @@ -57,7 +57,16 @@ can be: can be: .nf - path relative to the controller hierarchy (ex. pgrp1/gid1/uid1) - + - following strings will get expanded + + %u username, uid if name resolving fails + %U uid + %g group name, gid if name resolving fails + %G gid + %p process name, pid if name not available + %P pid + + '\\' can be used to escape '%' .fi First rule which matches the criteria will be executed. diff --git a/src/api.c b/src/api.c index fa4f02e..e6ca8db 100644 --- a/src/api.c +++ b/src/api.c @@ -2393,6 +2393,14 @@ 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; + int written; + int available; + struct passwd *user_info; + struct group *group_info; + /* Return codes */ int ret = 0; @@ -2445,7 +2453,92 @@ 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) && + (j < FILENAME_MAX - 2); ++i, ++j) { + if(tmp->destination[i] == '%') { + /* How many bytes did we write / error check */ + written = 0; + /* How many bytes can we write */ + available = FILENAME_MAX - j - 2; + /* Substitution */ + switch(tmp->destination[++i]) { + case 'u': + written = snprintf(newdest+j, available, + "%d", uid); + break; + case 'U': + user_info = getpwuid(uid); + if(user_info) { + written = snprintf(newdest + j, + available, "%s", + user_info -> pw_name); + } else { + written = snprintf(newdest + j, + available, "%d", uid); + } + break; + case 'g': + written = snprintf(newdest + j, + available, "%d", gid); + break; + case 'G': + group_info = getgrgid(gid); + if(group_info) { + written = snprintf(newdest + j, + available, "%s", + group_info -> gr_name); + } else { + written = snprintf(newdest + j, + available, "%d", gid); + } + break; + case 'p': + written = snprintf(newdest + j, + available, "%d", pid); + break; + case 'P': + if(procname) { + written = snprintf(newdest + j, + available, "%s", + procname); + } else { + written = snprintf(newdest + j, + available, "%d", pid); + } + break; + } + written = min(written, available); + /* + * written<1 only when either error occurred + * during snprintf or if no substitution was + * made at all. In both cases, we want to just + * copy input string. + */ + if(written<1) { + newdest[j] = '%'; + if(available>1) + newdest[++j] = + tmp->destination[i]; + } else { + /* + * In next iteration, we will write + * just after the substitution, but j + * will get incremented in the + * meantime. + */ + j += written - 1; + } + } else { + if(tmp->destination[i] == '\\') + ++i; + newdest[j] = tmp->destination[i]; + } + } + newdest[j] = 0; + + /* Apply the rule */ + 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.4 ------------------------------------------------------------------------------ Learn how Oracle Real Application Clusters (RAC) One Node allows customers to consolidate database storage, standardize their database environment, and, should the need arise, upgrade to a full multi-node Oracle RAC database without downtime or disruption http://p.sf.net/sfu/oracle-sfdevnl _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel