2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1988, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A/* Copyright (c) 1988 AT&T */ 2N/A/* All Rights Reserved */ 2N/A * Compatibility routines to read and write alternate 2N/A * utmp-like files. These routines are only used in 2N/A * the case where utmpname() is used to change to a file 2N/A * we assume that someone really wants to read old utmp-format 2N/A * files. Otherwise, the getutent, setutent, getutid, setutline, 2N/A * and pututline functions are actually wrappers around the 2N/A * equivalent function operating on utmpx-like files. 2N/A#
define MAXVAL 255 /* max value for an id 'character' */ 2N/Astatic int idcmp(
const char *,
const char *);
2N/Astatic int fd = -
1;
/* File descriptor for the utmp file. */ 2N/A * name of the current utmp-like file - set by utmpname (getutx.c) 2N/A * only if running in backward compatibility mode 2N/A * We don't modify this, but we can't declare it const or lint will freak. 2N/Astatic long loc_utmp;
/* Where in "utmp" the current "ubuf" was found. */ 2N/Astatic struct utmp ubuf;
/* Last entry returned to client */ 2N/A * In the 64-bit world, the utmp data structure grows because of 2N/A * the ut_time field (a time_t) at the end of it. 2N/A * "getutent_frec" gets the raw version of the next entry in the utmp file. 2N/A * If the "utmp" file is not open, attempt to open it for 2N/A * reading. If there is no file, attempt to create one. If 2N/A * both attempts fail, return NULL. If the file exists, but 2N/A * isn't readable and writeable, do not attempt to create. 2N/A * If the open failed for permissions, try opening 2N/A * it only for reading. All "pututline()" later 2N/A * will fail the writes. 2N/A /* Try to read in the next entry from the utmp file. */ 2N/A /* Save the location in the file where this entry was found. */ 2N/A * "_compat_getutent" gets the next entry in the utmp file. 2N/A * "_compat_getutid" finds the specified entry in the utmp file. If 2N/A * it can't find it, it returns NULL. 2N/A * Start looking for entry. Look in our current buffer before 2N/A * reading in new entries. 2N/A * If there is no entry in "ubuf", skip to the read. 2N/A * Do not look for an entry if the user sent 2N/A * us an EMPTY entry. 2N/A * For RUN_LVL, BOOT_TIME, DOWN_TIME, 2N/A * OLD_TIME, and NEW_TIME entries, only the 2N/A * types have to match. If they do, return 2N/A * the address of internal buffer. 2N/A * For INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, 2N/A * and DEAD_PROCESS the type of the entry in "fubuf", 2N/A * must be one of the above and id's must match. 2N/A /* Do not search for illegal types of entry. */ 2N/A /* the proper entry wasn't found. */ 2N/A * "_compat_getutline" searches the "utmp" file for a LOGIN_PROCESS or 2N/A * USER_PROCESS with the same "line" as the specified "entry". 2N/A * If the current entry is the one we are interested in, 2N/A * return a pointer to it. 2N/A * "_compat_pututline" writes the structure sent into the utmp file 2N/A * If there is already an entry with the same id, then it is 2N/A * overwritten, otherwise a new entry is made at the end of the 2N/A * Copy the user supplied entry into our temporary buffer to 2N/A * avoid the possibility that the user is actually passing us 2N/A * the address of "ubuf". 2N/A gdebug(
"pututline: Unable to create utmp file.\n");
2N/A /* Make sure file is writable */ 2N/A * Find the proper entry in the utmp file. Start at the current 2N/A * location. If it isn't found from here to the end of the 2N/A * file, then reset to the beginning of the file and try again. 2N/A * If it still isn't found, then write a new entry at the end of 2N/A * the file. (Making sure the location is an integral number of 2N/A * utmp structures into the file incase the file is scribbled.) 2N/A gdebug(
"2nd getutid() failed. fd: %d loc_utmp: %ld\n",
2N/A * Write out the user supplied structure. If the write fails, 2N/A * then the user probably doesn't have permission to write the 2N/A * Copy the new user structure into ubuf so that it will 2N/A * be up to date in the future. 2N/A * "_compat_setutent" just resets the utmp file back to the beginning. 2N/A * Zero the stored copy of the last entry read, since we are 2N/A * resetting to the beginning of the file. 2N/A * "_compat_endutent" closes the utmp file. 2N/A * If one of wtmp and wtmpx files exist, create the other, and the record. 2N/A * If they both exist add the record. 2N/A * makeut - create a utmp entry, recycling an id if a wild card is 2N/A * args: utmp - point to utmp structure to be created 2N/A struct utmp *
utp;
/* "current" utmp entry being examined */ 2N/A int wild;
/* flag, true iff wild card char seen */ 2N/A /* the last id we matched that was NOT a dead proc */ 2N/A * try to lock the utmp file, only needed if we're 2N/A * doing wildcard matching 2N/A /* find the first alphanumeric character */ 2N/A * found an unused entry, reuse it 2N/A * nothing available, try to allocate an id 2N/A * _compat_modut - modify a utmp entry. 2N/A * args: utmp - point to utmp structure to be created 2N/A int i;
/* scratch variable */ 2N/A struct utmp *
up;
/* "current" utmp entry being examined */ 2N/A /* copy the supplied utmp structure someplace safe */ 2N/A * idcmp - compare two id strings, return 0 if same, non-zero if not * 2N/A * args: s1 - first id string 2N/A * s2 - second id string 2N/A * allocid - allocate an unused id for utmp, either by recycling a 2N/A * DEAD_PROCESS entry or creating a new one. This routine only 2N/A * gets called if a wild card character was specified. 2N/A * args: srcid - pattern for new id 2N/A * saveid - last id matching pattern for a non-dead process 2N/A int i;
/* scratch variable */ 2N/A int changed;
/* flag to indicate that a new id has been generated */ 2N/A * if this character isn't wild, it'll 2N/A * be part of the generated id 2N/A * it's a wild character, retrieve the 2N/A * character from the saved id 2N/A * if we haven't changed anything yet, 2N/A * try to find a new char to use 2N/A * Note: this algorithm is taking the "last matched" id and trying to make 2N/A * a 1 character change to it to create a new one. Rather than special-case 2N/A * the first time (when no perturbation is really necessary), just don't 2N/A * allocate the first valid id. 2N/A /* make sure new char is alphanumeric */ 2N/A * Then 'reset' the current count at 2N/A * this position to it's lowest valid 2N/A * value, and propagate the carry to 2N/A * the next wild-card slot 2N/A /* changed is true if we were successful in allocating an id */ 2N/A * lockut - lock utmp file 2N/A * unlockut - unlock utmp file