1 #include "config.h"
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <libgen.h>
8 #include <limits.h>
9 #include <pwd.h>
10
11 #define TEST_PASSWD "test/test.passwd"
12 static char pwfile[PATH_MAX];
13 static void setup_pwfile() __attribute__((constructor));
14
15 static void setup_pwfile() {
16 snprintf(pwfile, sizeof(pwfile), "%s/%s", BASEDIR, TEST_PASSWD);
17 }
18
19 #define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
20 #define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1)
21
22 static int test_getpwent_r(FILE *file, struct passwd *pwd, char *buf,
23 size_t buflen, struct passwd **result)
24 {
25 char *str, *line;
26 int index = 0;
27
28 *result = NULL;
29
30 line = fgets(buf, buflen, file);
31 if (!line) {
32 return 0;
33 }
34
35 while ((str = strtok(line, ":"))) {
36 switch (index++) {
37 case 0:
38 pwd->pw_name = str;
39 break;
40 case 1:
41 pwd->pw_passwd = str;
42 break;
43 case 2:
44 errno = 0;
45 pwd->pw_uid = strtol(str, NULL, 10);
46 if (errno)
47 return -1;
48 break;
49 case 3:
50 errno = 0;
51 pwd->pw_gid = strtol(str, NULL, 10);
52 if (errno)
53 return -1;
54 break;
55 case 4:
56 pwd->pw_gecos = str;
57 break;
58 case 5:
59 pwd->pw_dir = str;
60 break;
61 case 6:
62 pwd->pw_shell = str;
63 break;
64 }
65 line = NULL;
66 }
67
68 *result = pwd;
69
70 return 0;
71 }
72
73 static int test_getpw_match(struct passwd *pwd, char *buf, size_t buflen,
74 struct passwd **result,
75 int (*match)(const struct passwd *, const void *),
76 const void *data)
77 {
78 FILE *file;
79 struct passwd *_result;
80
81 *result = NULL;
82
83 file = fopen(pwfile, "r");
84 if (!file) {
85 fprintf(stderr, "Failed to open %s\n", pwfile);
86 errno = EBADF;
87 return -1;
88 }
89
90 errno = 0;
91 while (!test_getpwent_r(file, pwd, buf, buflen, &_result)) {
92 if (!_result)
93 break;
94 else if (match(pwd, data)) {
95 *result = pwd;
96 break;
97 }
98 }
99
100 fclose(file);
101 if (!errno && !*result)
102 errno = ENOENT;
103 if (errno)
104 return -1;
105 return 0;
106 }
107
108 static int match_name(const struct passwd *pwd, const void *data)
109 {
110 const char *name = data;
111 return !strcmp(pwd->pw_name, name);
112 }
113
114 EXPORT
115 int getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen,
116 struct passwd **result)
117 {
118 return test_getpw_match(pwd, buf, buflen, result, match_name, name);
119 }
120
121 EXPORT
122 struct passwd *getpwnam(const char *name)
123 {
124 static char buf[16384];
125 static struct passwd pwd;
126 struct passwd *result;
127
128 (void) getpwnam_r(name, &pwd, buf, sizeof(buf), &result);
129 return result;
130 }
131
132 static int match_uid(const struct passwd *pwd, const void *data)
133 {
134 uid_t uid = *(uid_t *)data;
135 return pwd->pw_uid == uid;
136 }
137
138 EXPORT
139 int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen,
140 struct passwd **result)
141 {
142 return test_getpw_match(pwd, buf, buflen, result, match_uid, &uid);
143 }
144
145 EXPORT
146 struct passwd *getpwuid(uid_t uid)
147 {
148 static char buf[16384];
149 static struct passwd pwd;
150 struct passwd *result;
151
152 (void) getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
153 return result;
154 }