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