112 lines
2.5 KiB
C
112 lines
2.5 KiB
C
/*
|
|
* islocal.c - returns true if user is registered in the local
|
|
* /etc/passwd file. Written by Álvaro Martínez 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 <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "closestream.h"
|
|
#include "islocal.h"
|
|
#include "nls.h"
|
|
#include "pathnames.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]) {
|
|
/* Success. */
|
|
local = 1;
|
|
/* next line has no test coverage,
|
|
* but it is just an optimisation
|
|
* anyway. */
|
|
break;
|
|
}
|
|
/* 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)
|
|
err(EXIT_FAILURE, _("cannot open %s"), _PATH_PASSWD);
|
|
return rv;
|
|
}
|
|
|
|
#ifdef TEST_PROGRAM
|
|
int main(int argc, char *argv[])
|
|
{
|
|
close_stdout_atexit();
|
|
if (argc <= 2) {
|
|
fprintf(stderr, _("Usage: %s <passwordfile> <username>...\n"),
|
|
argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
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
|