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