* libmisc/limits.c: Re-indent.

* libmisc/limits.c: Reformat the documentation. Avoid personal
	comments.
	* man/limits.5.xml: Document the new features.
This commit is contained in:
nekral-guest 2010-03-18 23:20:24 +00:00
parent 52c2bb51fb
commit dfce564026
2 changed files with 95 additions and 69 deletions

View File

@ -1,10 +1,15 @@
2010-03-18 Nicolas François <nicolas.francois@centraliens.net>
* libmisc/limits.c: Re-indent.
* libmisc/limits.c: Reformat the documentation. Avoid personal
comments.
* man/limits.5.xml: Document the new features.
2010-03-18 Thomas Orgis <thomas@orgis.org> 2010-03-18 Thomas Orgis <thomas@orgis.org>
* NEWS, libmisc/limits.c: Fix parsing of limits. * NEWS, libmisc/limits.c: Fix parsing of limits.
* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for * NEWS, libmisc/limits.c: Add support for infinite limits.
infinite limits. * NEWS, libmisc/limits.c: Add support for @group syntax.
* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for @group
syntax.
2010-03-18 Nicolas François <nicolas.francois@centraliens.net> 2010-03-18 Nicolas François <nicolas.francois@centraliens.net>

View File

@ -33,7 +33,7 @@
/* /*
* Separated from setup.c. --marekm * Separated from setup.c. --marekm
* Resource limits thanks to Cristian Gafton. * Resource limits thanks to Cristian Gafton.
* Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org> ("thor"). * Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org>
*/ */
#include <config.h> #include <config.h>
@ -66,36 +66,40 @@
* value - string value to be read * value - string value to be read
* multiplier - value*multiplier is the actual limit * multiplier - value*multiplier is the actual limit
*/ */
static int static int setrlimit_value (unsigned int resource,
setrlimit_value (unsigned int resource, const char *value, const char *value,
unsigned int multiplier) unsigned int multiplier)
{ {
struct rlimit rlim; struct rlimit rlim;
rlim_t limit; rlim_t limit;
/* The "-" is special, not belonging to a strange negative limit. /* The "-" is special, not belonging to a strange negative limit.
It is infinity, in a controlled way. --thor */ * It is infinity, in a controlled way.
if(value[0] == '-') { */
if ('-' == value[0]) {
limit = RLIM_INFINITY; limit = RLIM_INFINITY;
} }
else { else {
/* We cannot use getlong here because it fails when there /* We cannot use getlong here because it fails when there
is more to the value than just this number! * is more to the value than just this number!
Also, we are limited to base 10 here (hex numbers will not * Also, we are limited to base 10 here (hex numbers will not
work with the limit string parser as is anyway) --thor */ * work with the limit string parser as is anyway)
*/
char *endptr; char *endptr;
long longlimit = strtol (value, &endptr, 10); long longlimit = strtol (value, &endptr, 10);
if ((0 == longlimit) && (value == endptr)) { if ((0 == longlimit) && (value == endptr)) {
/* No argument at all. No-op. /* No argument at all. No-op.
We could instead throw an error, though. --thor */ * FIXME: We could instead throw an error, though.
*/
return 0; return 0;
} }
longlimit *= multiplier; longlimit *= multiplier;
limit = (rlim_t)longlimit; limit = (rlim_t)longlimit;
if (longlimit != limit) if (longlimit != limit)
{ {
/* Again, silent error handling... I left it that way. /* FIXME: Again, silent error handling...
Wouldn't screaming make more sense? --thor */ * Wouldn't screaming make more sense?
*/
return 0; return 0;
} }
} }
@ -221,8 +225,8 @@ static int check_logins (const char *name, const char *maxlogins)
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19) * [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO) * [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
* *
* Remember to extend the "no-limits" string below when adding a new limit... * NOTE: Remember to extend the "no-limits" string below when adding a new
* --thor * limit...
* *
* Return value: * Return value:
* 0 = okay, of course * 0 = okay, of course
@ -239,17 +243,22 @@ static int do_user_limits (const char *buf, const char *name)
bool reported = false; bool reported = false;
pp = buf; pp = buf;
/* Skip leading whitespace. --thor */ /* Skip leading whitespace. */
while(*pp == ' ' || *pp == '\t') ++pp; while ((' ' == *pp) || ('\t' == *pp)) {
pp++;
}
/* The special limit string "-" results in no limit for all known limits. /* The special limit string "-" results in no limit for all known
We achieve that by parsing a full limit string, parts of it being ignored * limits.
if a limit type is not known to the system. * We achieve that by parsing a full limit string, parts of it
Though, there will be complaining for unknown limit types. --thor */ * being ignored if a limit type is not known to the system.
* Though, there will be complaining for unknown limit types.
*/
if (strcmp (pp, "-") == 0) { if (strcmp (pp, "-") == 0) {
/* Remember to extend this, too, when adding new limits! /* Remember to extend this, too, when adding new limits!
Oh... but "unlimited" does not make sense for umask, or does it? * Oh... but "unlimited" does not make sense for umask,
--thor */ * or does it?
*/
pp = "A- C- D- F- M- N- R- S- T- P- I- O-"; pp = "A- C- D- F- M- N- R- S- T- P- I- O-";
} }
@ -354,10 +363,12 @@ static int do_user_limits (const char *buf, const char *name)
break; break;
default: default:
/* Only report invalid strings once */ /* Only report invalid strings once */
/* Note: A string can be invalid just because a specific (theoretically /* Note: A string can be invalid just because a
valid) setting is not supported by this build. * specific (theoretically valid) setting is not
It is just a warning in syslog anyway. The line is still processed * supported by this build.
--thor */ * It is just a warning in syslog anyway. The line
* is still processed
*/
if (!reported) { if (!reported) {
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN,
"Invalid limit string: '%s'", "Invalid limit string: '%s'",
@ -366,13 +377,18 @@ static int do_user_limits (const char *buf, const char *name)
retval |= LOGIN_ERROR_RLIMIT; retval |= LOGIN_ERROR_RLIMIT;
} }
} }
/* After parsing one limit setting (or just complaining about it), /* After parsing one limit setting (or just complaining
one still needs to skip its argument to prevent a bogus warning on * about it), one still needs to skip its argument to
trying to parse that as limit specification. * prevent a bogus warning on trying to parse that as
So, let's skip all digits, "-" and our limited set of whitespace. * limit specification.
--thor */ * So, let's skip all digits, "-" and our limited set of
while(isdigit(*pp) || *pp == '-' || *pp == ' ' || *pp == '\t') { * whitespace.
++pp; */
while ( isdigit (*pp)
|| ('-' == *pp)
|| (' ' == *pp)
|| ('\t' ==*pp)) {
pp++;
} }
} }
return retval; return retval;
@ -381,32 +397,28 @@ static int do_user_limits (const char *buf, const char *name)
/* Check if user uname is in the group gname. /* Check if user uname is in the group gname.
* Can I be sure that gr_mem contains no UID as string? * Can I be sure that gr_mem contains no UID as string?
* Returns true when user is in the group, false when not. * Returns true when user is in the group, false when not.
* Any error is treated as false. --thor * Any error is treated as false.
*/ */
static bool user_in_group (const char *uname, const char *gname) static bool user_in_group (const char *uname, const char *gname)
{ {
struct group *groupdata; struct group *groupdata;
char **member; char **member;
if (uname == NULL || gname == NULL){ if (uname == NULL || gname == NULL){
return false; return false;
} }
/* We are not claiming to be re-entrant! /* We are not claiming to be re-entrant!
* In case of paranoia or a multithreaded login program, * In case of paranoia or a multithreaded login program,
* one needs to add some mess for getgrnam_r. */ * one needs to add some mess for getgrnam_r. */
groupdata = getgrnam (gname); groupdata = getgrnam (gname);
if(groupdata == NULL) { if (NULL == groupdata) {
SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.", gname)); SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.",
gname));
return false; return false;
} }
/* Now look for our user in the list of members. */
member = groupdata->gr_mem; return is_on_list (groupdata->gr_mem, uname);
while(*member != NULL) {
if(strcmp(*member, uname) == 0) {
return true;
}
++member;
}
return false;
} }
static int setup_user_limits (const char *uname) static int setup_user_limits (const char *uname)
@ -432,8 +444,10 @@ static int setup_user_limits (const char *uname)
} }
/* The limits file have the following format: /* The limits file have the following format:
* - '#' (comment) chars only as first chars on a line; * - '#' (comment) chars only as first chars on a line;
* - username must start on first column (or *, or @group --thor) * - username must start on first column (or *, or @group)
* A better (smarter) checking should be done --cristiang */ *
* FIXME: A better (smarter) checking should be done
*/
while (fgets (buf, 1024, fil) != NULL) { while (fgets (buf, 1024, fil) != NULL) {
if (('#' == buf[0]) || ('\n' == buf[0])) { if (('#' == buf[0]) || ('\n' == buf[0])) {
continue; continue;
@ -445,15 +459,20 @@ static int setup_user_limits (const char *uname)
* username L2 D2048 R4096 * username L2 D2048 R4096
* where spaces={' ',\t}. Also, we reject invalid limits. * where spaces={' ',\t}. Also, we reject invalid limits.
* Imposing a limit should be done with care, so a wrong * Imposing a limit should be done with care, so a wrong
* entry means no care anyway :-). A '-' as a limits * entry means no care anyway :-).
* strings means no limits --cristiang */ *
/* In addition to the handling of * as name which was alrady present, * A '-' as a limits strings means no limits
I added handling of the @group syntax. *
To clarify: The first entry with matching user name rules, * The username can also be:
everything after it is ignored. If there is no user entry, * '*': the default limits (only the last is taken into
the last encountered entry for a matching group rules. * account)
If there is no matching group entry, the default limits rule. * @group: the limit applies to the members of the group
--thor. */ *
* To clarify: The first entry with matching user name rules,
* everything after it is ignored. If there is no user entry,
* the last encountered entry for a matching group rules.
* If there is no matching group entry, the default limits rule.
*/
if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]", if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]",
name, tempbuf) == 2) { name, tempbuf) == 2) {
if (strcmp (name, uname) == 0) { if (strcmp (name, uname) == 0) {
@ -462,8 +481,10 @@ static int setup_user_limits (const char *uname)
} else if (strcmp (name, "*") == 0) { } else if (strcmp (name, "*") == 0) {
strcpy (deflimits, tempbuf); strcpy (deflimits, tempbuf);
} else if (name[0] == '@') { } else if (name[0] == '@') {
/* If the user is in the group, the group limits apply unless /* If the user is in the group, the group
later a line for the specific user is found. --thor */ * limits apply unless later a line for
* the specific user is found.
*/
if (user_in_group (uname, name+1)) { if (user_in_group (uname, name+1)) {
strcpy (limits, tempbuf); strcpy (limits, tempbuf);
} }