]> git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/islocal.c
Merge branch 'login-utils' of https://github.com/kerolasa/lelux-utiliteetit
[thirdparty/util-linux.git] / login-utils / islocal.c
1 /*
2 * islocal.c - returns true if user is registered in the local
3 * /etc/passwd file. Written by Alvaro Martinez Echevarria,
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 *
13 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
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 */
20
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "islocal.h"
26 #include "nls.h"
27 #include "pathnames.h"
28
29 static int is_local_in_file(const char *user, const char *filename)
30 {
31 int local = 0;
32 size_t match;
33 int chin, skip;
34 FILE *f;
35
36 if (NULL == (f = fopen(filename, "r")))
37 return -1;
38
39 match = 0u;
40 skip = 0;
41 while ((chin = getc(f)) != EOF) {
42 if (skip) {
43 /* Looking for the start of the next line. */
44 if ('\n' == chin) {
45 /* Start matching username at the next char. */
46 skip = 0;
47 match = 0u;
48 }
49 } else {
50 if (':' == chin) {
51 if (0 == user[match]) {
52 /* Success. */
53 local = 1;
54 /* next line has no test coverage,
55 * but it is just an optimisation
56 * anyway. */
57 break;
58 } else {
59 /* we read a whole username, but it
60 * is the wrong user. Skip to the
61 * next line. */
62 skip = 1;
63 }
64 } else if ('\n' == chin) {
65 /* This line contains no colon; it's
66 * malformed. No skip since we are already
67 * at the start of the next line. */
68 match = 0u;
69 } else if (chin != user[match]) {
70 /* username does not match. */
71 skip = 1;
72 } else {
73 ++match;
74 }
75 }
76 }
77 fclose(f);
78 return local;
79 }
80
81 int is_local(const char *user)
82 {
83 int rv;
84 if ((rv = is_local_in_file(user, _PATH_PASSWD)) < 0) {
85 perror(_PATH_PASSWD);
86 fprintf(stderr, _("Failed to open %s for reading, exiting."),
87 _PATH_PASSWD);
88 exit(1);
89 } else {
90 return rv;
91 }
92 }
93
94 #ifdef TEST_PROGRAM
95 int main(int argc, char *argv[])
96 {
97 if (argc <= 2) {
98 fprintf(stderr, "usage: %s <passwdfile> <username> [...]\n",
99 argv[0]);
100 return 1;
101 } else {
102 int i;
103 for (i = 2; i < argc; i++) {
104 const int rv = is_local_in_file(argv[i], argv[1]);
105 if (rv < 0) {
106 perror(argv[1]);
107 return 2;
108 }
109 printf("%d:%s\n", rv, argv[i]);
110 }
111 return 0;
112 }
113 }
114 #endif