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 44a627ac61SEd Schouten int 45a627ac61SEd Schouten setutxdb(int db, const char *file) 46a627ac61SEd Schouten { 47a627ac61SEd Schouten struct stat sb; 48a627ac61SEd Schouten 49a627ac61SEd Schouten switch (db) { 50a627ac61SEd Schouten case UTXDB_ACTIVE: 51a627ac61SEd Schouten if (file == NULL) 52a627ac61SEd Schouten file = _PATH_UTX_ACTIVE; 53a627ac61SEd Schouten break; 54a627ac61SEd Schouten case UTXDB_LASTLOGIN: 55a627ac61SEd Schouten if (file == NULL) 56a627ac61SEd Schouten file = _PATH_UTX_LASTLOGIN; 57a627ac61SEd Schouten break; 58a627ac61SEd Schouten case UTXDB_LOG: 59a627ac61SEd Schouten if (file == NULL) 60a627ac61SEd Schouten file = _PATH_UTX_LOG; 61a627ac61SEd Schouten break; 62a627ac61SEd Schouten default: 63a627ac61SEd Schouten errno = EINVAL; 64a627ac61SEd Schouten return (-1); 65a627ac61SEd Schouten } 66a627ac61SEd Schouten 67a627ac61SEd Schouten if (uf != NULL) 68a627ac61SEd Schouten fclose(uf); 69a627ac61SEd Schouten uf = fopen(file, "r"); 70a627ac61SEd Schouten if (uf == NULL) 71a627ac61SEd Schouten return (-1); 72a627ac61SEd Schouten 73a627ac61SEd Schouten /* Safety check: never use broken files. */ 74a627ac61SEd Schouten if (db != UTXDB_LOG && _fstat(fileno(uf), &sb) != -1 && 75a627ac61SEd Schouten sb.st_size % sizeof(struct futx) != 0) { 76a627ac61SEd Schouten fclose(uf); 77a627ac61SEd Schouten uf = NULL; 78a627ac61SEd Schouten errno = EFTYPE; 79a627ac61SEd Schouten return (-1); 80a627ac61SEd Schouten } 81a627ac61SEd Schouten 82a627ac61SEd Schouten udb = db; 83a627ac61SEd Schouten return (0); 84a627ac61SEd Schouten } 85a627ac61SEd Schouten 86a627ac61SEd Schouten void 87a627ac61SEd Schouten setutxent(void) 88a627ac61SEd Schouten { 89a627ac61SEd Schouten 90a627ac61SEd Schouten setutxdb(UTXDB_ACTIVE, NULL); 91a627ac61SEd Schouten } 92a627ac61SEd Schouten 93a627ac61SEd Schouten void 94a627ac61SEd Schouten endutxent(void) 95a627ac61SEd Schouten { 96a627ac61SEd Schouten 97a627ac61SEd Schouten if (uf != NULL) { 98a627ac61SEd Schouten fclose(uf); 99a627ac61SEd Schouten uf = NULL; 100a627ac61SEd Schouten } 101a627ac61SEd Schouten } 102a627ac61SEd Schouten 10398c63a48SEd Schouten static int 10498c63a48SEd Schouten getfutxent(struct futx *fu) 105a627ac61SEd Schouten { 106a627ac61SEd Schouten 107a627ac61SEd Schouten if (uf == NULL) 108a627ac61SEd Schouten setutxent(); 109a627ac61SEd Schouten if (uf == NULL) 11098c63a48SEd Schouten return (-1); 111a627ac61SEd Schouten 112a627ac61SEd Schouten if (udb == UTXDB_LOG) { 113a627ac61SEd Schouten uint16_t len; 114a627ac61SEd Schouten 115*1ae6a21dSEd Schouten if (fread(&len, sizeof(len), 1, uf) != 1) 11698c63a48SEd Schouten return (-1); 117a627ac61SEd Schouten len = be16toh(len); 11898c63a48SEd Schouten if (len > sizeof *fu) { 119a627ac61SEd Schouten /* Forward compatibility. */ 120*1ae6a21dSEd Schouten if (fread(fu, sizeof(*fu), 1, uf) != 1) 12198c63a48SEd Schouten return (-1); 122*1ae6a21dSEd Schouten fseek(uf, len - sizeof(*fu), SEEK_CUR); 123a627ac61SEd Schouten } else { 124a627ac61SEd Schouten /* Partial record. */ 125*1ae6a21dSEd Schouten memset(fu, 0, sizeof(*fu)); 12698c63a48SEd Schouten if (fread(fu, len, 1, uf) != 1) 12798c63a48SEd Schouten return (-1); 128a627ac61SEd Schouten } 129a627ac61SEd Schouten } else { 130*1ae6a21dSEd Schouten if (fread(fu, sizeof(*fu), 1, uf) != 1) 13198c63a48SEd Schouten return (-1); 132a627ac61SEd Schouten } 13398c63a48SEd Schouten return (0); 134a627ac61SEd Schouten } 135a627ac61SEd Schouten 136a627ac61SEd Schouten struct utmpx * 137a627ac61SEd Schouten getutxent(void) 138a627ac61SEd Schouten { 13998c63a48SEd Schouten struct futx fu; 140a627ac61SEd Schouten 14198c63a48SEd Schouten if (getfutxent(&fu) != 0) 142a627ac61SEd Schouten return (NULL); 14398c63a48SEd Schouten return (futx_to_utx(&fu)); 144a627ac61SEd Schouten } 145a627ac61SEd Schouten 146a627ac61SEd Schouten struct utmpx * 147a627ac61SEd Schouten getutxid(const struct utmpx *id) 148a627ac61SEd Schouten { 14998c63a48SEd Schouten struct futx fu; 150a627ac61SEd Schouten 151a627ac61SEd Schouten for (;;) { 15298c63a48SEd Schouten if (getfutxent(&fu) != 0) 153a627ac61SEd Schouten return (NULL); 154a627ac61SEd Schouten 15598c63a48SEd Schouten switch (fu.fu_type) { 156a627ac61SEd Schouten case USER_PROCESS: 157a627ac61SEd Schouten case INIT_PROCESS: 158a627ac61SEd Schouten case LOGIN_PROCESS: 159a627ac61SEd Schouten case DEAD_PROCESS: 160a627ac61SEd Schouten switch (id->ut_type) { 161a627ac61SEd Schouten case USER_PROCESS: 162a627ac61SEd Schouten case INIT_PROCESS: 163a627ac61SEd Schouten case LOGIN_PROCESS: 164a627ac61SEd Schouten case DEAD_PROCESS: 16598c63a48SEd Schouten if (memcmp(fu.fu_id, id->ut_id, 166*1ae6a21dSEd Schouten MIN(sizeof(fu.fu_id), sizeof(id->ut_id))) == 167*1ae6a21dSEd Schouten 0) 168a627ac61SEd Schouten goto found; 169a627ac61SEd Schouten } 170e35a88d3SEd Schouten break; 17198c63a48SEd Schouten default: 17298c63a48SEd Schouten if (fu.fu_type == id->ut_type) 17398c63a48SEd Schouten goto found; 17498c63a48SEd Schouten break; 175a627ac61SEd Schouten } 176a627ac61SEd Schouten } 177a627ac61SEd Schouten 178a627ac61SEd Schouten found: 17998c63a48SEd Schouten return (futx_to_utx(&fu)); 180a627ac61SEd Schouten } 181a627ac61SEd Schouten 182a627ac61SEd Schouten struct utmpx * 183a627ac61SEd Schouten getutxline(const struct utmpx *line) 184a627ac61SEd Schouten { 18598c63a48SEd Schouten struct futx fu; 186a627ac61SEd Schouten 187a627ac61SEd Schouten for (;;) { 18898c63a48SEd Schouten if (getfutxent(&fu) != 0) 189a627ac61SEd Schouten return (NULL); 190a627ac61SEd Schouten 19198c63a48SEd Schouten switch (fu.fu_type) { 192a627ac61SEd Schouten case USER_PROCESS: 193a627ac61SEd Schouten case LOGIN_PROCESS: 19498c63a48SEd Schouten if (strncmp(fu.fu_line, line->ut_line, 195*1ae6a21dSEd Schouten MIN(sizeof(fu.fu_line), sizeof(line->ut_line))) == 196*1ae6a21dSEd Schouten 0) 197a627ac61SEd Schouten goto found; 19898c63a48SEd Schouten break; 199a627ac61SEd Schouten } 200a627ac61SEd Schouten } 201a627ac61SEd Schouten 202a627ac61SEd Schouten found: 20398c63a48SEd Schouten return (futx_to_utx(&fu)); 204a627ac61SEd Schouten } 205a627ac61SEd Schouten 206a627ac61SEd Schouten struct utmpx * 207a627ac61SEd Schouten getutxuser(const char *user) 208a627ac61SEd Schouten { 20998c63a48SEd Schouten struct futx fu; 210a627ac61SEd Schouten 211a627ac61SEd Schouten for (;;) { 21298c63a48SEd Schouten if (getfutxent(&fu) != 0) 213a627ac61SEd Schouten return (NULL); 214a627ac61SEd Schouten 21598c63a48SEd Schouten switch (fu.fu_type) { 216a627ac61SEd Schouten case USER_PROCESS: 217*1ae6a21dSEd Schouten if (strncmp(fu.fu_user, user, sizeof(fu.fu_user)) == 0) 218a627ac61SEd Schouten goto found; 21998c63a48SEd Schouten break; 220a627ac61SEd Schouten } 221a627ac61SEd Schouten } 222a627ac61SEd Schouten 223a627ac61SEd Schouten found: 22498c63a48SEd Schouten return (futx_to_utx(&fu)); 225a627ac61SEd Schouten } 226