* 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:
parent
52c2bb51fb
commit
dfce564026
13
ChangeLog
13
ChangeLog
@ -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>
|
||||||
|
|
||||||
|
135
libmisc/limits.c
135
libmisc/limits.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user