File: utmp2.c

package info (click to toggle)
libc-sparc 5.3.12-2
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 18,664 kB
  • ctags: 53,237
  • sloc: ansic: 181,379; asm: 5,080; makefile: 3,340; lex: 521; sh: 439; yacc: 401; awk: 28
file content (163 lines) | stat: -rw-r--r-- 3,897 bytes parent folder | download | duplicates (2)
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;
}