xref: /freebsd/lib/libc/gen/getutxent.c (revision e35a88d3a6fab90e9faa70cd25334847d1868b0c)
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 
41a627ac61SEd Schouten static FILE *uf = NULL;
42a627ac61SEd Schouten static int udb;
43a627ac61SEd Schouten static struct utmpx utx;
44a627ac61SEd Schouten 
45a627ac61SEd Schouten int
46a627ac61SEd Schouten setutxdb(int db, const char *file)
47a627ac61SEd Schouten {
48a627ac61SEd Schouten 	struct stat sb;
49a627ac61SEd Schouten 
50a627ac61SEd Schouten 	switch (db) {
51a627ac61SEd Schouten 	case UTXDB_ACTIVE:
52a627ac61SEd Schouten 		if (file == NULL)
53a627ac61SEd Schouten 			file = _PATH_UTX_ACTIVE;
54a627ac61SEd Schouten 		break;
55a627ac61SEd Schouten 	case UTXDB_LASTLOGIN:
56a627ac61SEd Schouten 		if (file == NULL)
57a627ac61SEd Schouten 			file = _PATH_UTX_LASTLOGIN;
58a627ac61SEd Schouten 		break;
59a627ac61SEd Schouten 	case UTXDB_LOG:
60a627ac61SEd Schouten 		if (file == NULL)
61a627ac61SEd Schouten 			file = _PATH_UTX_LOG;
62a627ac61SEd Schouten 		break;
63a627ac61SEd Schouten 	default:
64a627ac61SEd Schouten 		errno = EINVAL;
65a627ac61SEd Schouten 		return (-1);
66a627ac61SEd Schouten 	}
67a627ac61SEd Schouten 
68a627ac61SEd Schouten 	if (uf != NULL)
69a627ac61SEd Schouten 		fclose(uf);
70a627ac61SEd Schouten 	uf = fopen(file, "r");
71a627ac61SEd Schouten 	if (uf == NULL)
72a627ac61SEd Schouten 		return (-1);
73a627ac61SEd Schouten 
74a627ac61SEd Schouten 	/* Safety check: never use broken files. */
75a627ac61SEd Schouten 	if (db != UTXDB_LOG && _fstat(fileno(uf), &sb) != -1 &&
76a627ac61SEd Schouten 	    sb.st_size % sizeof(struct futx) != 0) {
77a627ac61SEd Schouten 		fclose(uf);
78a627ac61SEd Schouten 		uf = NULL;
79a627ac61SEd Schouten 		errno = EFTYPE;
80a627ac61SEd Schouten 		return (-1);
81a627ac61SEd Schouten 	}
82a627ac61SEd Schouten 
83a627ac61SEd Schouten 	udb = db;
84a627ac61SEd Schouten 	return (0);
85a627ac61SEd Schouten }
86a627ac61SEd Schouten 
87a627ac61SEd Schouten void
88a627ac61SEd Schouten setutxent(void)
89a627ac61SEd Schouten {
90a627ac61SEd Schouten 
91a627ac61SEd Schouten 	setutxdb(UTXDB_ACTIVE, NULL);
92a627ac61SEd Schouten }
93a627ac61SEd Schouten 
94a627ac61SEd Schouten void
95a627ac61SEd Schouten endutxent(void)
96a627ac61SEd Schouten {
97a627ac61SEd Schouten 
98a627ac61SEd Schouten 	if (uf != NULL) {
99a627ac61SEd Schouten 		fclose(uf);
100a627ac61SEd Schouten 		uf = NULL;
101a627ac61SEd Schouten 	}
102a627ac61SEd Schouten }
103a627ac61SEd Schouten 
104a627ac61SEd Schouten static struct futx *
105a627ac61SEd Schouten getfutxent(void)
106a627ac61SEd Schouten {
107a627ac61SEd Schouten 	static struct futx fu;
108a627ac61SEd Schouten 
109a627ac61SEd Schouten 	if (uf == NULL)
110a627ac61SEd Schouten 		setutxent();
111a627ac61SEd Schouten 	if (uf == NULL)
112a627ac61SEd Schouten 		return (NULL);
113a627ac61SEd Schouten 
114a627ac61SEd Schouten 	if (udb == UTXDB_LOG) {
115a627ac61SEd Schouten 		uint16_t len;
116a627ac61SEd Schouten 
117a627ac61SEd Schouten 		if (fread(&len, sizeof len, 1, uf) != 1)
118a627ac61SEd Schouten 			return (NULL);
119a627ac61SEd Schouten 		len = be16toh(len);
120a627ac61SEd Schouten 		if (len > sizeof fu) {
121a627ac61SEd Schouten 			/* Forward compatibility. */
122a627ac61SEd Schouten 			if (fread(&fu, sizeof fu, 1, uf) != 1)
123a627ac61SEd Schouten 				return (NULL);
124a627ac61SEd Schouten 			fseek(uf, len - sizeof fu, SEEK_CUR);
125a627ac61SEd Schouten 		} else {
126a627ac61SEd Schouten 			/* Partial record. */
127a627ac61SEd Schouten 			memset(&fu, 0, sizeof fu);
128a627ac61SEd Schouten 			if (fread(&fu, len, 1, uf) != 1)
129a627ac61SEd Schouten 				return (NULL);
130a627ac61SEd Schouten 		}
131a627ac61SEd Schouten 	} else {
132a627ac61SEd Schouten 		if (fread(&fu, sizeof fu, 1, uf) != 1)
133a627ac61SEd Schouten 			return (NULL);
134a627ac61SEd Schouten 	}
135a627ac61SEd Schouten 	return (&fu);
136a627ac61SEd Schouten }
137a627ac61SEd Schouten 
138a627ac61SEd Schouten struct utmpx *
139a627ac61SEd Schouten getutxent(void)
140a627ac61SEd Schouten {
141a627ac61SEd Schouten 	struct futx *fu;
142a627ac61SEd Schouten 
143a627ac61SEd Schouten 	fu = getfutxent();
144a627ac61SEd Schouten 	if (fu == NULL)
145a627ac61SEd Schouten 		return (NULL);
146a627ac61SEd Schouten 	futx_to_utx(fu, &utx);
147a627ac61SEd Schouten 	return (&utx);
148a627ac61SEd Schouten }
149a627ac61SEd Schouten 
150a627ac61SEd Schouten struct utmpx *
151a627ac61SEd Schouten getutxid(const struct utmpx *id)
152a627ac61SEd Schouten {
153a627ac61SEd Schouten 	struct futx *fu;
154a627ac61SEd Schouten 
155a627ac61SEd Schouten 	for (;;) {
156a627ac61SEd Schouten 		fu = getfutxent();
157a627ac61SEd Schouten 		if (fu == NULL)
158a627ac61SEd Schouten 			return (NULL);
159a627ac61SEd Schouten 
160a627ac61SEd Schouten 		switch (fu->fu_type) {
161a627ac61SEd Schouten 		case BOOT_TIME:
162a627ac61SEd Schouten 		case OLD_TIME:
163a627ac61SEd Schouten 		case NEW_TIME:
164a627ac61SEd Schouten 		case SHUTDOWN_TIME:
165a627ac61SEd Schouten 			if (fu->fu_type == id->ut_type)
166a627ac61SEd Schouten 				goto found;
167e35a88d3SEd Schouten 			break;
168a627ac61SEd Schouten 		case USER_PROCESS:
169a627ac61SEd Schouten 		case INIT_PROCESS:
170a627ac61SEd Schouten 		case LOGIN_PROCESS:
171a627ac61SEd Schouten 		case DEAD_PROCESS:
172a627ac61SEd Schouten 			switch (id->ut_type) {
173a627ac61SEd Schouten 			case USER_PROCESS:
174a627ac61SEd Schouten 			case INIT_PROCESS:
175a627ac61SEd Schouten 			case LOGIN_PROCESS:
176a627ac61SEd Schouten 			case DEAD_PROCESS:
177a627ac61SEd Schouten 				if (memcmp(fu->fu_id, id->ut_id,
178a627ac61SEd Schouten 				    MIN(sizeof fu->fu_id, sizeof id->ut_id)) == 0)
179a627ac61SEd Schouten 					goto found;
180a627ac61SEd Schouten 			}
181e35a88d3SEd Schouten 			break;
182a627ac61SEd Schouten 		}
183a627ac61SEd Schouten 	}
184a627ac61SEd Schouten 
185a627ac61SEd Schouten found:
186a627ac61SEd Schouten 	futx_to_utx(fu, &utx);
187a627ac61SEd Schouten 	return (&utx);
188a627ac61SEd Schouten }
189a627ac61SEd Schouten 
190a627ac61SEd Schouten struct utmpx *
191a627ac61SEd Schouten getutxline(const struct utmpx *line)
192a627ac61SEd Schouten {
193a627ac61SEd Schouten 	struct futx *fu;
194a627ac61SEd Schouten 
195a627ac61SEd Schouten 	for (;;) {
196a627ac61SEd Schouten 		fu = getfutxent();
197a627ac61SEd Schouten 		if (fu == NULL)
198a627ac61SEd Schouten 			return (NULL);
199a627ac61SEd Schouten 
200a627ac61SEd Schouten 		switch (fu->fu_type) {
201a627ac61SEd Schouten 		case USER_PROCESS:
202a627ac61SEd Schouten 		case LOGIN_PROCESS:
203a627ac61SEd Schouten 			if (strncmp(fu->fu_line, line->ut_line,
204a627ac61SEd Schouten 			    MIN(sizeof fu->fu_line, sizeof line->ut_line)) == 0)
205a627ac61SEd Schouten 				goto found;
206a627ac61SEd Schouten 		}
207a627ac61SEd Schouten 	}
208a627ac61SEd Schouten 
209a627ac61SEd Schouten found:
210a627ac61SEd Schouten 	futx_to_utx(fu, &utx);
211a627ac61SEd Schouten 	return (&utx);
212a627ac61SEd Schouten }
213a627ac61SEd Schouten 
214a627ac61SEd Schouten struct utmpx *
215a627ac61SEd Schouten getutxuser(const char *user)
216a627ac61SEd Schouten {
217a627ac61SEd Schouten 	struct futx *fu;
218a627ac61SEd Schouten 
219a627ac61SEd Schouten 	for (;;) {
220a627ac61SEd Schouten 		fu = getfutxent();
221a627ac61SEd Schouten 		if (fu == NULL)
222a627ac61SEd Schouten 			return (NULL);
223a627ac61SEd Schouten 
224a627ac61SEd Schouten 		switch (fu->fu_type) {
225a627ac61SEd Schouten 		case USER_PROCESS:
226a627ac61SEd Schouten 			if (strncmp(fu->fu_user, user, sizeof fu->fu_user) == 0)
227a627ac61SEd Schouten 				goto found;
228a627ac61SEd Schouten 		}
229a627ac61SEd Schouten 	}
230a627ac61SEd Schouten 
231a627ac61SEd Schouten found:
232a627ac61SEd Schouten 	futx_to_utx(fu, &utx);
233a627ac61SEd Schouten 	return (&utx);
234a627ac61SEd Schouten }
235