]>
Commit | Line | Data |
---|---|---|
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 | 30 | static 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; | |
42 | while ((chin = getc(f)) != EOF) { | |
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 JY |
58 | break; |
59 | } else { | |
43b53f57 SK |
60 | /* we read a whole username, but it |
61 | * is the wrong user. Skip to the | |
62 | * next line. */ | |
8e025972 JY |
63 | skip = 1; |
64 | } | |
65 | } else if ('\n' == chin) { | |
43b53f57 SK |
66 | /* This line contains no colon; it's |
67 | * malformed. No skip since we are already | |
68 | * at the start of the next line. */ | |
8e025972 JY |
69 | match = 0u; |
70 | } else if (chin != user[match]) { | |
71 | /* username does not match. */ | |
72 | skip = 1; | |
73 | } else { | |
74 | ++match; | |
75 | } | |
76 | } | |
6dbe3af9 | 77 | } |
8e025972 | 78 | fclose(f); |
6dbe3af9 KZ |
79 | return local; |
80 | } | |
81 | ||
43b53f57 | 82 | int is_local(const char *user) |
8e025972 JY |
83 | { |
84 | int rv; | |
58fbb9b2 SK |
85 | |
86 | if ((rv = is_local_in_file(user, _PATH_PASSWD)) < 0) | |
87 | err(EXIT_FAILURE, _("cannot open %s"), _PATH_PASSWD); | |
88 | return rv; | |
8e025972 JY |
89 | } |
90 | ||
c293a7e8 | 91 | #ifdef TEST_PROGRAM |
43b53f57 | 92 | int main(int argc, char *argv[]) |
8e025972 | 93 | { |
2c308875 | 94 | close_stdout_atexit(); |
c293a7e8 | 95 | if (argc <= 2) { |
0429455a | 96 | fprintf(stderr, _("Usage: %s <passwordfile> <username>...\n"), |
43b53f57 | 97 | argv[0]); |
8e025972 JY |
98 | return 1; |
99 | } else { | |
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; | |
106 | } | |
107 | printf("%d:%s\n", rv, argv[i]); | |
108 | } | |
109 | return 0; | |
110 | } | |
111 | } | |
112 | #endif |