1202188Sed/*- 2202188Sed * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org> 3202188Sed * All rights reserved. 4202188Sed * 5202188Sed * Redistribution and use in source and binary forms, with or without 6202188Sed * modification, are permitted provided that the following conditions 7202188Sed * are met: 8202188Sed * 1. Redistributions of source code must retain the above copyright 9202188Sed * notice, this list of conditions and the following disclaimer. 10202188Sed * 2. Redistributions in binary form must reproduce the above copyright 11202188Sed * notice, this list of conditions and the following disclaimer in the 12202188Sed * documentation and/or other materials provided with the distribution. 13202188Sed * 14202188Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15202188Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16202188Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17202188Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18202188Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19202188Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20202188Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21202188Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22202188Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23202188Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24202188Sed * SUCH DAMAGE. 25202188Sed */ 26202188Sed 27202188Sed#include <sys/cdefs.h> 28202188Sed__FBSDID("$FreeBSD$"); 29202188Sed 30202188Sed#include "namespace.h" 31202188Sed#include <sys/endian.h> 32202188Sed#include <sys/param.h> 33202188Sed#include <sys/stat.h> 34202188Sed#include <errno.h> 35202188Sed#include <stdio.h> 36202188Sed#include <string.h> 37202188Sed#include <utmpx.h> 38202188Sed#include "utxdb.h" 39202188Sed#include "un-namespace.h" 40202188Sed 41202188Sedstatic FILE *uf = NULL; 42202188Sedstatic int udb; 43202188Sed 44202188Sedint 45202188Sedsetutxdb(int db, const char *file) 46202188Sed{ 47202188Sed struct stat sb; 48202188Sed 49202188Sed switch (db) { 50202188Sed case UTXDB_ACTIVE: 51202188Sed if (file == NULL) 52202188Sed file = _PATH_UTX_ACTIVE; 53202188Sed break; 54202188Sed case UTXDB_LASTLOGIN: 55202188Sed if (file == NULL) 56202188Sed file = _PATH_UTX_LASTLOGIN; 57202188Sed break; 58202188Sed case UTXDB_LOG: 59202188Sed if (file == NULL) 60202188Sed file = _PATH_UTX_LOG; 61202188Sed break; 62202188Sed default: 63202188Sed errno = EINVAL; 64202188Sed return (-1); 65202188Sed } 66202188Sed 67202188Sed if (uf != NULL) 68202188Sed fclose(uf); 69202188Sed uf = fopen(file, "r"); 70202188Sed if (uf == NULL) 71202188Sed return (-1); 72202188Sed 73232408Sed if (db != UTXDB_LOG) { 74232408Sed /* Safety check: never use broken files. */ 75232408Sed if (_fstat(fileno(uf), &sb) != -1 && 76232408Sed sb.st_size % sizeof(struct futx) != 0) { 77232408Sed fclose(uf); 78232408Sed uf = NULL; 79232408Sed errno = EFTYPE; 80232408Sed return (-1); 81232408Sed } 82232408Sed /* Prevent reading of partial records. */ 83232408Sed (void)setvbuf(uf, NULL, _IOFBF, 84232408Sed rounddown(BUFSIZ, sizeof(struct futx))); 85202188Sed } 86202188Sed 87202188Sed udb = db; 88202188Sed return (0); 89202188Sed} 90202188Sed 91202188Sedvoid 92202188Sedsetutxent(void) 93202188Sed{ 94202188Sed 95202188Sed setutxdb(UTXDB_ACTIVE, NULL); 96202188Sed} 97202188Sed 98202188Sedvoid 99202188Sedendutxent(void) 100202188Sed{ 101202188Sed 102202188Sed if (uf != NULL) { 103202188Sed fclose(uf); 104202188Sed uf = NULL; 105202188Sed } 106202188Sed} 107202188Sed 108202530Sedstatic int 109202530Sedgetfutxent(struct futx *fu) 110202188Sed{ 111202188Sed 112202188Sed if (uf == NULL) 113202188Sed setutxent(); 114202188Sed if (uf == NULL) 115202530Sed return (-1); 116202188Sed 117202188Sed if (udb == UTXDB_LOG) { 118202188Sed uint16_t len; 119202188Sed 120218846Sed if (fread(&len, sizeof(len), 1, uf) != 1) 121202530Sed return (-1); 122202188Sed len = be16toh(len); 123202530Sed if (len > sizeof *fu) { 124202188Sed /* Forward compatibility. */ 125218846Sed if (fread(fu, sizeof(*fu), 1, uf) != 1) 126202530Sed return (-1); 127218846Sed fseek(uf, len - sizeof(*fu), SEEK_CUR); 128202188Sed } else { 129202188Sed /* Partial record. */ 130218846Sed memset(fu, 0, sizeof(*fu)); 131202530Sed if (fread(fu, len, 1, uf) != 1) 132202530Sed return (-1); 133202188Sed } 134202188Sed } else { 135218846Sed if (fread(fu, sizeof(*fu), 1, uf) != 1) 136202530Sed return (-1); 137202188Sed } 138202530Sed return (0); 139202188Sed} 140202188Sed 141202188Sedstruct utmpx * 142202188Sedgetutxent(void) 143202188Sed{ 144202530Sed struct futx fu; 145202188Sed 146202530Sed if (getfutxent(&fu) != 0) 147202188Sed return (NULL); 148202530Sed return (futx_to_utx(&fu)); 149202188Sed} 150202188Sed 151202188Sedstruct utmpx * 152202188Sedgetutxid(const struct utmpx *id) 153202188Sed{ 154202530Sed struct futx fu; 155202188Sed 156202188Sed for (;;) { 157202530Sed if (getfutxent(&fu) != 0) 158202188Sed return (NULL); 159202188Sed 160202530Sed switch (fu.fu_type) { 161202188Sed case USER_PROCESS: 162202188Sed case INIT_PROCESS: 163202188Sed case LOGIN_PROCESS: 164202188Sed case DEAD_PROCESS: 165202188Sed switch (id->ut_type) { 166202188Sed case USER_PROCESS: 167202188Sed case INIT_PROCESS: 168202188Sed case LOGIN_PROCESS: 169202188Sed case DEAD_PROCESS: 170202530Sed if (memcmp(fu.fu_id, id->ut_id, 171218846Sed MIN(sizeof(fu.fu_id), sizeof(id->ut_id))) == 172218846Sed 0) 173202188Sed goto found; 174202188Sed } 175202527Sed break; 176202530Sed default: 177202530Sed if (fu.fu_type == id->ut_type) 178202530Sed goto found; 179202530Sed break; 180202188Sed } 181202188Sed } 182202188Sed 183202188Sedfound: 184202530Sed return (futx_to_utx(&fu)); 185202188Sed} 186202188Sed 187202188Sedstruct utmpx * 188202188Sedgetutxline(const struct utmpx *line) 189202188Sed{ 190202530Sed struct futx fu; 191202188Sed 192202188Sed for (;;) { 193202530Sed if (getfutxent(&fu) != 0) 194202188Sed return (NULL); 195202188Sed 196202530Sed switch (fu.fu_type) { 197202188Sed case USER_PROCESS: 198202188Sed case LOGIN_PROCESS: 199202530Sed if (strncmp(fu.fu_line, line->ut_line, 200218846Sed MIN(sizeof(fu.fu_line), sizeof(line->ut_line))) == 201218846Sed 0) 202202188Sed goto found; 203202530Sed break; 204202188Sed } 205202188Sed } 206202188Sed 207202188Sedfound: 208202530Sed return (futx_to_utx(&fu)); 209202188Sed} 210202188Sed 211202188Sedstruct utmpx * 212202188Sedgetutxuser(const char *user) 213202188Sed{ 214202530Sed struct futx fu; 215202188Sed 216202188Sed for (;;) { 217202530Sed if (getfutxent(&fu) != 0) 218202188Sed return (NULL); 219202188Sed 220202530Sed switch (fu.fu_type) { 221202188Sed case USER_PROCESS: 222218846Sed if (strncmp(fu.fu_user, user, sizeof(fu.fu_user)) == 0) 223202188Sed goto found; 224202530Sed break; 225202188Sed } 226202188Sed } 227202188Sed 228202188Sedfound: 229202530Sed return (futx_to_utx(&fu)); 230202188Sed} 231