blob: 762a4e9900db8006e3e276d326da9cfce8af611b [file] [log] [blame]
/*
islocal.c - returns true if user is registered in the local
/etc/passwd file. Written by Alvaro Martinez Echevarria,
alvaro@enano.etsit.upm.es, to allow peaceful coexistence with yp. Nov 94.
Hacked a bit by poe@daimi.aau.dk
See also ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil*
Hacked by Peter Breitenlohner, peb@mppmu.mpg.de,
to distinguish user names where one is a prefix of the other,
and to use "pathnames.h". Oct 5, 96.
1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
- added Native Language Support
2008-04-06 James Youngman, jay@gnu.org
- Completely rewritten to remove assumption that /etc/passwd
lines are < 1024 characters long. Also added unit tests.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nls.h"
#include "pathnames.h"
#include "islocal.h"
static int
is_local_in_file(const char *user, const char *filename)
{
int local = 0;
size_t match;
int chin, skip;
FILE *f;
if (NULL == (f=fopen(filename, "r")))
return -1;
match = 0u;
skip = 0;
while ((chin = getc(f)) != EOF) {
if (skip) {
/* Looking for the start of the next line. */
if ('\n' == chin) {
/* Start matching username at the next char. */
skip = 0;
match = 0u;
}
} else {
if (':' == chin) {
if (0 == user[match]) {
local = 1; /* Success. */
/* next line has no test coverage, but it is
* just an optimisation anyway. */
break;
} else {
/* we read a whole username, but it is
* the wrong user. Skip to the next
* line. */
skip = 1;
}
} else if ('\n' == chin) {
/* This line contains no colon; it's malformed.
* No skip since we are already at the start of
* the next line. */
match = 0u;
} else if (chin != user[match]) {
/* username does not match. */
skip = 1;
} else {
++match;
}
}
}
fclose(f);
return local;
}
int
is_local(const char *user)
{
int rv;
if ((rv = is_local_in_file(user, _PATH_PASSWD)) < 0) {
perror(_PATH_PASSWD);
fprintf(stderr, _("Failed to open %s for reading, exiting."),
_PATH_PASSWD);
exit(1);
} else {
return rv;
}
}
#if MAIN_TEST_ISLOCAL
int
main (int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "No test passwd file was specified.\n");
return 1;
} else {
int i;
for (i = 2; i < argc; i++) {
const int rv = is_local_in_file(argv[i], argv[1]);
if (rv < 0) {
perror(argv[1]);
return 2;
}
printf("%d:%s\n", rv, argv[i]);
}
return 0;
}
}
#endif