/* 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 - 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 #include #include #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