xref: /freebsd/lib/libc/gen/getutxent.c (revision 126b6df920a055e7d01ee9f92e9d5735542ad98c)
1a627ac61SEd Schouten /*-
2a627ac61SEd Schouten  * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
3a627ac61SEd Schouten  * All rights reserved.
4a627ac61SEd Schouten  *
5a627ac61SEd Schouten  * Redistribution and use in source and binary forms, with or without
6a627ac61SEd Schouten  * modification, are permitted provided that the following conditions
7a627ac61SEd Schouten  * are met:
8a627ac61SEd Schouten  * 1. Redistributions of source code must retain the above copyright
9a627ac61SEd Schouten  *    notice, this list of conditions and the following disclaimer.
10a627ac61SEd Schouten  * 2. Redistributions in binary form must reproduce the above copyright
11a627ac61SEd Schouten  *    notice, this list of conditions and the following disclaimer in the
12a627ac61SEd Schouten  *    documentation and/or other materials provided with the distribution.
13a627ac61SEd Schouten  *
14a627ac61SEd Schouten  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15a627ac61SEd Schouten  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16a627ac61SEd Schouten  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17a627ac61SEd Schouten  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18a627ac61SEd Schouten  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19a627ac61SEd Schouten  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20a627ac61SEd Schouten  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21a627ac61SEd Schouten  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22a627ac61SEd Schouten  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23a627ac61SEd Schouten  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24a627ac61SEd Schouten  * SUCH DAMAGE.
25a627ac61SEd Schouten  */
26a627ac61SEd Schouten 
27a627ac61SEd Schouten #include <sys/cdefs.h>
28a627ac61SEd Schouten __FBSDID("$FreeBSD$");
29a627ac61SEd Schouten 
30a627ac61SEd Schouten #include "namespace.h"
31a627ac61SEd Schouten #include <sys/endian.h>
32a627ac61SEd Schouten #include <sys/param.h>
33a627ac61SEd Schouten #include <sys/stat.h>
34a627ac61SEd Schouten #include <errno.h>
35a627ac61SEd Schouten #include <stdio.h>
36a627ac61SEd Schouten #include <string.h>
37a627ac61SEd Schouten #include <utmpx.h>
38a627ac61SEd Schouten #include "utxdb.h"
39a627ac61SEd Schouten #include "un-namespace.h"
40a627ac61SEd Schouten 
41*126b6df9SEd Schouten #ifdef __NO_TLS
42a627ac61SEd Schouten static FILE *uf = NULL;
43a627ac61SEd Schouten static int udb;
44*126b6df9SEd Schouten #else
45*126b6df9SEd Schouten static _Thread_local FILE *uf = NULL;
46*126b6df9SEd Schouten static _Thread_local int udb;
47*126b6df9SEd Schouten #endif
48a627ac61SEd Schouten 
49a627ac61SEd Schouten int
50a627ac61SEd Schouten setutxdb(int db, const char *file)
51a627ac61SEd Schouten {
52a627ac61SEd Schouten 	struct stat sb;
53a627ac61SEd Schouten 
54a627ac61SEd Schouten 	switch (db) {
55a627ac61SEd Schouten 	case UTXDB_ACTIVE:
56a627ac61SEd Schouten 		if (file == NULL)
57a627ac61SEd Schouten 			file = _PATH_UTX_ACTIVE;
58a627ac61SEd Schouten 		break;
59a627ac61SEd Schouten 	case UTXDB_LASTLOGIN:
60a627ac61SEd Schouten 		if (file == NULL)
61a627ac61SEd Schouten 			file = _PATH_UTX_LASTLOGIN;
62a627ac61SEd Schouten 		break;
63a627ac61SEd Schouten 	case UTXDB_LOG:
64a627ac61SEd Schouten 		if (file == NULL)
65a627ac61SEd Schouten 			file = _PATH_UTX_LOG;
66a627ac61SEd Schouten 		break;
67a627ac61SEd Schouten 	default:
68a627ac61SEd Schouten 		errno = EINVAL;
69a627ac61SEd Schouten 		return (-1);
70a627ac61SEd Schouten 	}
71a627ac61SEd Schouten 
72a627ac61SEd Schouten 	if (uf != NULL)
73a627ac61SEd Schouten 		fclose(uf);
74a627ac61SEd Schouten 	uf = fopen(file, "r");
75a627ac61SEd Schouten 	if (uf == NULL)
76a627ac61SEd Schouten 		return (-1);
77a627ac61SEd Schouten 
78a8f77c1fSEd Schouten 	if (db != UTXDB_LOG) {
79a627ac61SEd Schouten 		/* Safety check: never use broken files. */
80a8f77c1fSEd Schouten 		if (_fstat(fileno(uf), &sb) != -1 &&
81a627ac61SEd Schouten 		    sb.st_size % sizeof(struct futx) != 0) {
82a627ac61SEd Schouten 			fclose(uf);
83a627ac61SEd Schouten 			uf = NULL;
84a627ac61SEd Schouten 			errno = EFTYPE;
85a627ac61SEd Schouten 			return (-1);
86a627ac61SEd Schouten 		}
87a8f77c1fSEd Schouten 		/* Prevent reading of partial records. */
88a8f77c1fSEd Schouten 		(void)setvbuf(uf, NULL, _IOFBF,
89a8f77c1fSEd Schouten 		    rounddown(BUFSIZ, sizeof(struct futx)));
90a8f77c1fSEd Schouten 	}
91a627ac61SEd Schouten 
92a627ac61SEd Schouten 	udb = db;
93a627ac61SEd Schouten 	return (0);
94a627ac61SEd Schouten }
95a627ac61SEd Schouten 
96a627ac61SEd Schouten void
97a627ac61SEd Schouten setutxent(void)
98a627ac61SEd Schouten {
99a627ac61SEd Schouten 
100a627ac61SEd Schouten 	setutxdb(UTXDB_ACTIVE, NULL);
101a627ac61SEd Schouten }
102a627ac61SEd Schouten 
103a627ac61SEd Schouten void
104a627ac61SEd Schouten endutxent(void)
105a627ac61SEd Schouten {
106a627ac61SEd Schouten 
107a627ac61SEd Schouten 	if (uf != NULL) {
108a627ac61SEd Schouten 		fclose(uf);
109a627ac61SEd Schouten 		uf = NULL;
110a627ac61SEd Schouten 	}
111a627ac61SEd Schouten }
112a627ac61SEd Schouten 
11398c63a48SEd Schouten static int
11498c63a48SEd Schouten getfutxent(struct futx *fu)
115a627ac61SEd Schouten {
116a627ac61SEd Schouten 
117a627ac61SEd Schouten 	if (uf == NULL)
118a627ac61SEd Schouten 		setutxent();
119a627ac61SEd Schouten 	if (uf == NULL)
12098c63a48SEd Schouten 		return (-1);
121a627ac61SEd Schouten 
122a627ac61SEd Schouten 	if (udb == UTXDB_LOG) {
123a627ac61SEd Schouten 		uint16_t len;
124a627ac61SEd Schouten 
1251ae6a21dSEd Schouten 		if (fread(&len, sizeof(len), 1, uf) != 1)
12698c63a48SEd Schouten 			return (-1);
127a627ac61SEd Schouten 		len = be16toh(len);
12898c63a48SEd Schouten 		if (len > sizeof *fu) {
129a627ac61SEd Schouten 			/* Forward compatibility. */
1301ae6a21dSEd Schouten 			if (fread(fu, sizeof(*fu), 1, uf) != 1)
13198c63a48SEd Schouten 				return (-1);
1321ae6a21dSEd Schouten 			fseek(uf, len - sizeof(*fu), SEEK_CUR);
133a627ac61SEd Schouten 		} else {
134a627ac61SEd Schouten 			/* Partial record. */
1351ae6a21dSEd Schouten 			memset(fu, 0, sizeof(*fu));
13698c63a48SEd Schouten 			if (fread(fu, len, 1, uf) != 1)
13798c63a48SEd Schouten 				return (-1);
138a627ac61SEd Schouten 		}
139a627ac61SEd Schouten 	} else {
1401ae6a21dSEd Schouten 		if (fread(fu, sizeof(*fu), 1, uf) != 1)
14198c63a48SEd Schouten 			return (-1);
142a627ac61SEd Schouten 	}
14398c63a48SEd Schouten 	return (0);
144a627ac61SEd Schouten }
145a627ac61SEd Schouten 
146a627ac61SEd Schouten struct utmpx *
147a627ac61SEd Schouten getutxent(void)
148a627ac61SEd Schouten {
14998c63a48SEd Schouten 	struct futx fu;
150a627ac61SEd Schouten 
15198c63a48SEd Schouten 	if (getfutxent(&fu) != 0)
152a627ac61SEd Schouten 		return (NULL);
15398c63a48SEd Schouten 	return (futx_to_utx(&fu));
154a627ac61SEd Schouten }
155a627ac61SEd Schouten 
156a627ac61SEd Schouten struct utmpx *
157a627ac61SEd Schouten getutxid(const struct utmpx *id)
158a627ac61SEd Schouten {
15998c63a48SEd Schouten 	struct futx fu;
160a627ac61SEd Schouten 
161a627ac61SEd Schouten 	for (;;) {
16298c63a48SEd Schouten 		if (getfutxent(&fu) != 0)
163a627ac61SEd Schouten 			return (NULL);
164a627ac61SEd Schouten 
16598c63a48SEd Schouten 		switch (fu.fu_type) {
166a627ac61SEd Schouten 		case USER_PROCESS:
167a627ac61SEd Schouten 		case INIT_PROCESS:
168a627ac61SEd Schouten 		case LOGIN_PROCESS:
169a627ac61SEd Schouten 		case DEAD_PROCESS:
170a627ac61SEd Schouten 			switch (id->ut_type) {
171a627ac61SEd Schouten 			case USER_PROCESS:
172a627ac61SEd Schouten 			case INIT_PROCESS:
173a627ac61SEd Schouten 			case LOGIN_PROCESS:
174a627ac61SEd Schouten 			case DEAD_PROCESS:
17598c63a48SEd Schouten 				if (memcmp(fu.fu_id, id->ut_id,
1761ae6a21dSEd Schouten 				    MIN(sizeof(fu.fu_id), sizeof(id->ut_id))) ==
1771ae6a21dSEd Schouten 				    0)
178a627ac61SEd Schouten 					goto found;
179a627ac61SEd Schouten 			}
180e35a88d3SEd Schouten 			break;
18198c63a48SEd Schouten 		default:
18298c63a48SEd Schouten 			if (fu.fu_type == id->ut_type)
18398c63a48SEd Schouten 				goto found;
18498c63a48SEd Schouten 			break;
185a627ac61SEd Schouten 		}
186a627ac61SEd Schouten 	}
187a627ac61SEd Schouten 
188a627ac61SEd Schouten found:
18998c63a48SEd Schouten 	return (futx_to_utx(&fu));
190a627ac61SEd Schouten }
191a627ac61SEd Schouten 
192a627ac61SEd Schouten struct utmpx *
193a627ac61SEd Schouten getutxline(const struct utmpx *line)
194a627ac61SEd Schouten {
19598c63a48SEd Schouten 	struct futx fu;
196a627ac61SEd Schouten 
197a627ac61SEd Schouten 	for (;;) {
19898c63a48SEd Schouten 		if (getfutxent(&fu) != 0)
199a627ac61SEd Schouten 			return (NULL);
200a627ac61SEd Schouten 
20198c63a48SEd Schouten 		switch (fu.fu_type) {
202a627ac61SEd Schouten 		case USER_PROCESS:
203a627ac61SEd Schouten 		case LOGIN_PROCESS:
20498c63a48SEd Schouten 			if (strncmp(fu.fu_line, line->ut_line,
2051ae6a21dSEd Schouten 			    MIN(sizeof(fu.fu_line), sizeof(line->ut_line))) ==
2061ae6a21dSEd Schouten 			    0)
207a627ac61SEd Schouten 				goto found;
20898c63a48SEd Schouten 			break;
209a627ac61SEd Schouten 		}
210a627ac61SEd Schouten 	}
211a627ac61SEd Schouten 
212a627ac61SEd Schouten found:
21398c63a48SEd Schouten 	return (futx_to_utx(&fu));
214a627ac61SEd Schouten }
215a627ac61SEd Schouten 
216a627ac61SEd Schouten struct utmpx *
217a627ac61SEd Schouten getutxuser(const char *user)
218a627ac61SEd Schouten {
21998c63a48SEd Schouten 	struct futx fu;
220a627ac61SEd Schouten 
221a627ac61SEd Schouten 	for (;;) {
22298c63a48SEd Schouten 		if (getfutxent(&fu) != 0)
223a627ac61SEd Schouten 			return (NULL);
224a627ac61SEd Schouten 
22598c63a48SEd Schouten 		switch (fu.fu_type) {
226a627ac61SEd Schouten 		case USER_PROCESS:
2271ae6a21dSEd Schouten 			if (strncmp(fu.fu_user, user, sizeof(fu.fu_user)) == 0)
228a627ac61SEd Schouten 				goto found;
22998c63a48SEd Schouten 			break;
230a627ac61SEd Schouten 		}
231a627ac61SEd Schouten 	}
232a627ac61SEd Schouten 
233a627ac61SEd Schouten found:
23498c63a48SEd Schouten 	return (futx_to_utx(&fu));
235a627ac61SEd Schouten }
236