diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 19:10:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 19:10:49 +0000 |
commit | cfe5e3905201349e9cf3f95d52ff4bd100bde37d (patch) | |
tree | d0baf160cbee3195249d095f85e52d20c21acf02 /login-utils/islocal.c | |
parent | Initial commit. (diff) | |
download | util-linux-cfe5e3905201349e9cf3f95d52ff4bd100bde37d.tar.xz util-linux-cfe5e3905201349e9cf3f95d52ff4bd100bde37d.zip |
Adding upstream version 2.39.3.upstream/2.39.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'login-utils/islocal.c')
-rw-r--r-- | login-utils/islocal.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/login-utils/islocal.c b/login-utils/islocal.c new file mode 100644 index 0000000..ab5c52e --- /dev/null +++ b/login-utils/islocal.c @@ -0,0 +1,111 @@ +/* + * 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 |