]> git.ipfire.org Git - thirdparty/util-linux.git/blame - login-utils/islocal.c
Merge branch 'PR/libmount-exec-errors' of github.com:karelzak/util-linux-work
[thirdparty/util-linux.git] / login-utils / islocal.c
CommitLineData
43b53f57
SK
1/*
2 * islocal.c - returns true if user is registered in the local
b50945d4 3 * /etc/passwd file. Written by Álvaro Martínez Echevarria,
43b53f57
SK
4 * alvaro@enano.etsit.upm.es, to allow peaceful coexistence with yp. Nov 94.
5 *
6 * Hacked a bit by poe@daimi.aau.dk
7 * See also ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil*
8 *
9 * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de,
10 * to distinguish user names where one is a prefix of the other,
11 * and to use "pathnames.h". Oct 5, 96.
12 *
b50945d4 13 * 1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
43b53f57
SK
14 * - added Native Language Support
15 *
16 * 2008-04-06 James Youngman, jay@gnu.org
17 * - Completely rewritten to remove assumption that /etc/passwd
18 * lines are < 1024 characters long. Also added unit tests.
19 */
6dbe3af9 20
43b53f57 21#include <stddef.h>
6dbe3af9 22#include <stdio.h>
66ee8158 23#include <stdlib.h>
6dbe3af9 24
439cdf1e 25#include "closestream.h"
43b53f57 26#include "islocal.h"
7eda085c 27#include "nls.h"
fd6b7a7f
KZ
28#include "pathnames.h"
29
43b53f57 30static int is_local_in_file(const char *user, const char *filename)
6dbe3af9 31{
6dbe3af9 32 int local = 0;
8e025972
JY
33 size_t match;
34 int chin, skip;
35 FILE *f;
36
43b53f57
SK
37 if (NULL == (f = fopen(filename, "r")))
38 return -1;
8e025972
JY
39
40 match = 0u;
41 skip = 0;
ccb3af02 42 while ((chin = fgetc(f)) != EOF) {
8e025972
JY
43 if (skip) {
44 /* Looking for the start of the next line. */
45 if ('\n' == chin) {
46 /* Start matching username at the next char. */
47 skip = 0;
48 match = 0u;
49 }
50 } else {
51 if (':' == chin) {
52 if (0 == user[match]) {
43b53f57
SK
53 /* Success. */
54 local = 1;
55 /* next line has no test coverage,
56 * but it is just an optimisation
57 * anyway. */
8e025972 58 break;
8e025972 59 }
042f62df
RP
60 /* we read a whole username, but it
61 * is the wrong user. Skip to the
62 * next line. */
63 skip = 1;
8e025972 64 } else if ('\n' == chin) {
43b53f57
SK
65 /* This line contains no colon; it's
66 * malformed. No skip since we are already
67 * at the start of the next line. */
8e025972
JY
68 match = 0u;
69 } else if (chin != user[match]) {
70 /* username does not match. */
71 skip = 1;
72 } else {
73 ++match;
74 }
75 }
6dbe3af9 76 }
8e025972 77 fclose(f);
6dbe3af9
KZ
78 return local;
79}
80
43b53f57 81int is_local(const char *user)
8e025972
JY
82{
83 int rv;
58fbb9b2
SK
84
85 if ((rv = is_local_in_file(user, _PATH_PASSWD)) < 0)
86 err(EXIT_FAILURE, _("cannot open %s"), _PATH_PASSWD);
87 return rv;
8e025972
JY
88}
89
c293a7e8 90#ifdef TEST_PROGRAM
43b53f57 91int main(int argc, char *argv[])
8e025972 92{
2c308875 93 close_stdout_atexit();
c293a7e8 94 if (argc <= 2) {
0429455a 95 fprintf(stderr, _("Usage: %s <passwordfile> <username>...\n"),
43b53f57 96 argv[0]);
8e025972 97 return 1;
042f62df
RP
98 }
99
100 int i;
101 for (i = 2; i < argc; i++) {
102 const int rv = is_local_in_file(argv[i], argv[1]);
103 if (rv < 0) {
104 perror(argv[1]);
105 return 2;
8e025972 106 }
042f62df 107 printf("%d:%s\n", rv, argv[i]);
8e025972 108 }
042f62df 109 return 0;
8e025972
JY
110}
111#endif