]> git.cameronkatri.com Git - getent-darwin.git/blob - getutxent.c
Move files around
[getent-darwin.git] / getutxent.c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "namespace.h"
33 #include <sys/endian.h>
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <utmpx.h>
40 #include "utxdb.h"
41 #include "un-namespace.h"
42
43 #ifdef __NO_TLS
44 static FILE *uf = NULL;
45 static int udb;
46 #else
47 static _Thread_local FILE *uf = NULL;
48 static _Thread_local int udb;
49 #endif
50
51 int
52 setutxdb(int db, const char *file)
53 {
54 struct stat sb;
55
56 switch (db) {
57 case UTXDB_ACTIVE:
58 if (file == NULL)
59 file = _PATH_UTX_ACTIVE;
60 break;
61 case UTXDB_LASTLOGIN:
62 if (file == NULL)
63 file = _PATH_UTX_LASTLOGIN;
64 break;
65 case UTXDB_LOG:
66 if (file == NULL)
67 file = _PATH_UTX_LOG;
68 break;
69 default:
70 errno = EINVAL;
71 return (-1);
72 }
73
74 if (uf != NULL)
75 fclose(uf);
76 uf = fopen(file, "re");
77 if (uf == NULL)
78 return (-1);
79
80 if (db != UTXDB_LOG) {
81 /* Safety check: never use broken files. */
82 if (_fstat(fileno(uf), &sb) != -1 &&
83 sb.st_size % sizeof(struct futx) != 0) {
84 fclose(uf);
85 uf = NULL;
86 errno = EFTYPE;
87 return (-1);
88 }
89 /* Prevent reading of partial records. */
90 (void)setvbuf(uf, NULL, _IOFBF,
91 rounddown(BUFSIZ, sizeof(struct futx)));
92 }
93
94 udb = db;
95 return (0);
96 }
97
98 void
99 setutxent(void)
100 {
101
102 setutxdb(UTXDB_ACTIVE, NULL);
103 }
104
105 void
106 endutxent(void)
107 {
108
109 if (uf != NULL) {
110 fclose(uf);
111 uf = NULL;
112 }
113 }
114
115 static int
116 getfutxent(struct futx *fu)
117 {
118
119 if (uf == NULL)
120 setutxent();
121 if (uf == NULL)
122 return (-1);
123
124 if (udb == UTXDB_LOG) {
125 uint16_t len;
126
127 retry:
128 if (fread(&len, sizeof(len), 1, uf) != 1)
129 return (-1);
130 len = be16toh(len);
131 if (len == 0) {
132 /*
133 * XXX: Though zero-size records are valid in theory,
134 * they can never occur in practice. Zero-size records
135 * indicate file corruption. Seek one byte forward, to
136 * see if we can find a record there.
137 */
138 ungetc('\0', uf);
139 goto retry;
140 }
141 if (len > sizeof *fu) {
142 /* Forward compatibility. */
143 if (fread(fu, sizeof(*fu), 1, uf) != 1)
144 return (-1);
145 fseek(uf, len - sizeof(*fu), SEEK_CUR);
146 } else {
147 /* Partial record. */
148 memset(fu, 0, sizeof(*fu));
149 if (fread(fu, len, 1, uf) != 1)
150 return (-1);
151 }
152 } else {
153 if (fread(fu, sizeof(*fu), 1, uf) != 1)
154 return (-1);
155 }
156 return (0);
157 }
158
159 struct utmpx *
160 getutxent(void)
161 {
162 struct futx fu;
163
164 if (getfutxent(&fu) != 0)
165 return (NULL);
166 return (futx_to_utx(&fu));
167 }
168
169 struct utmpx *
170 getutxid(const struct utmpx *id)
171 {
172 struct futx fu;
173
174 for (;;) {
175 if (getfutxent(&fu) != 0)
176 return (NULL);
177
178 switch (fu.fu_type) {
179 case USER_PROCESS:
180 case INIT_PROCESS:
181 case LOGIN_PROCESS:
182 case DEAD_PROCESS:
183 switch (id->ut_type) {
184 case USER_PROCESS:
185 case INIT_PROCESS:
186 case LOGIN_PROCESS:
187 case DEAD_PROCESS:
188 if (memcmp(fu.fu_id, id->ut_id,
189 MIN(sizeof(fu.fu_id), sizeof(id->ut_id))) ==
190 0)
191 goto found;
192 }
193 break;
194 default:
195 if (fu.fu_type == id->ut_type)
196 goto found;
197 break;
198 }
199 }
200
201 found:
202 return (futx_to_utx(&fu));
203 }
204
205 struct utmpx *
206 getutxline(const struct utmpx *line)
207 {
208 struct futx fu;
209
210 for (;;) {
211 if (getfutxent(&fu) != 0)
212 return (NULL);
213
214 switch (fu.fu_type) {
215 case USER_PROCESS:
216 case LOGIN_PROCESS:
217 if (strncmp(fu.fu_line, line->ut_line,
218 MIN(sizeof(fu.fu_line), sizeof(line->ut_line))) ==
219 0)
220 goto found;
221 break;
222 }
223 }
224
225 found:
226 return (futx_to_utx(&fu));
227 }
228
229 struct utmpx *
230 getutxuser(const char *user)
231 {
232 struct futx fu;
233
234 for (;;) {
235 if (getfutxent(&fu) != 0)
236 return (NULL);
237
238 switch (fu.fu_type) {
239 case USER_PROCESS:
240 if (strncmp(fu.fu_user, user, sizeof(fu.fu_user)) == 0)
241 goto found;
242 break;
243 }
244 }
245
246 found:
247 return (futx_to_utx(&fu));
248 }