1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/* utmp2.c for Linux, by poe@daimi.aau.dk */
/* This code is freely distributable and is covered by the GNU copyleft */
/* This implementation of the utmp and wtmp routines, is supposed to
conform to the XPG2 and SVID2 standards */
#include "utmp.h"
#include "utmp-wrap.h"
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
static char Utname[1024] = _PATH_UTMP;
static int Fd = -1;
static struct old_utmp Ut;
/* kludge for the benefit of getutent() whose semantics differs from the
other get..() functions. When set, getutent() will not read the
next entry in utmp, but immediatly returns &Ut, and resets the
flag. */
static int _getutent_flag = 0;
static int _old_setutent(void);
void old_setutent(void);
void old_utmpname(const char *name);
struct old_utmp *old_getutent(void);
struct old_utmp *old_getutid(struct old_utmp *ut);
struct old_utmp *old_getutline(struct old_utmp *ut);
static struct old_utmp *_pututline(struct old_utmp *ut);
void old_pututline(struct old_utmp *ut);
void old_endutent(void);
static int _old_setutent(void)
{
if(Fd != -1) close(Fd);
/* first try to get write permission, if that fails then
make do with read access */
if((Fd = open(Utname, O_RDWR)) < 0) {
if((Fd = open(Utname, O_RDONLY)) < 0) {
perror("_setutent: Can't open utmp file");
Fd = -1;
return 0;
}
}
if(read(Fd, (char *)&Ut, sizeof(Ut)) != sizeof(Ut)) {
Ut.ut_id[0]='\0';
return 0;
}
return 1;
}
void old_setutent(void)
{
(void)_old_setutent();
_getutent_flag = 1;
}
void old_utmpname(const char *name)
{
(void)strncpy(Utname, name, sizeof(Utname)-1);
if(Fd != -1) close(Fd);
Fd = -1;
}
/* always get the logical *next* entry from the utmp file */
struct old_utmp *old_getutent(void)
{
if(Fd == -1) {
if(!_old_setutent())
return (struct old_utmp *)0;
else {
_getutent_flag = 0;
return &Ut;
}
}
if(_getutent_flag) {
/* well, setutent() really got it for us */
_getutent_flag = 0;
return &Ut;
}
if(read(Fd, (char *)&Ut, sizeof(Ut)) != sizeof(Ut))
return (struct old_utmp *)0;
else
return &Ut;
}
struct old_utmp *old_getutid(struct old_utmp *ut)
{
if(Fd == -1)
if(!_old_setutent()) return (struct old_utmp *)0;
do {
if(RUN_LVL <= ut->ut_type && ut->ut_type <= OLD_TIME &&
Ut.ut_type == ut->ut_type) return &Ut;
if(INIT_PROCESS <= ut->ut_type && ut->ut_type <= DEAD_PROCESS &&
!strncmp(Ut.ut_id, ut->ut_id, sizeof(Ut.ut_id)))
return &Ut;
} while(read(Fd, (char *)&Ut, sizeof(Ut)) == sizeof(Ut));
return (struct old_utmp *)0;
}
struct old_utmp *old_getutline(struct old_utmp *ut)
{
if(Fd == -1)
if(!_old_setutent()) return (struct old_utmp *)0;
do {
if((Ut.ut_type == USER_PROCESS || Ut.ut_type == LOGIN_PROCESS)
&& !strncmp(Ut.ut_line, ut->ut_line, sizeof(Ut.ut_line)))
return &Ut;
} while(read(Fd, (char *)&Ut, sizeof(Ut)) == sizeof(Ut));
return (struct old_utmp *)0;
}
struct old_utmp *_pututline(struct old_utmp *ut)
{
struct old_utmp my_ut;
/* don't stomp on the new value even if it's in Ut */
if(ut == &Ut) {
(void)memcpy(&my_ut, &Ut, sizeof(Ut));
ut = &my_ut;
}
/* we don't check Fd here, getutid() does it for us; this way
we can create an utmp file from an empty file, if it should
get lost. */
if(old_getutid(ut)) {
(void)lseek(Fd, (off_t)-sizeof(Ut), SEEK_CUR);
if(write(Fd, (char *)ut, sizeof(Ut)) != sizeof(Ut))
return (struct old_utmp *)0;
} else {
(void)lseek(Fd, (off_t)0, SEEK_END);
if(write(Fd, (char *)ut, sizeof(Ut)) != sizeof(Ut))
return (struct old_utmp *)0;
}
/* if we get this far, we are successful */
if(ut == &my_ut)
(void)memcpy(&Ut, &my_ut, sizeof(Ut));
return &Ut;
}
void old_pututline(struct old_utmp *ut)
{
/* (void)_pututline(ut); */
if (_pututline(ut)==NULL) fprintf(stderr,"FEHLER\n");
}
void old_endutent(void)
{
if(Fd != -1) close(Fd);
Fd = -1;
}
|