3
Copyright 1990, 1998 The Open Group
4
Copyright 2005 Oswald Buddenhagen <ossi@kde.org>
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of The Open Group shall
24
not be used in advertising or otherwise to promote the sale, use or
25
other dealings in this Software without prior written authorization
32
Author: Keith Packard, MIT X Consortium
33
Lastlog support and dynamic utmp entry allocation
34
by Andreas Stolcke <stolcke@icsi.berkeley.edu>
38
#define _FILE_OFFSET_BITS 64
42
#if defined(__svr4__) || defined(__Lynx__) || defined(__QNX__) || defined(__APPLE__) || defined(_SEQUENT_) /*|| defined(USE_PAM)*/
46
# if __FreeBSD_version >= 900007
52
# ifdef HAVE_LASTLOG_H
56
# ifdef _PATH_LASTLOGX
57
# define LLOG_FILE _PATH_LASTLOGX
58
# elif defined(_PATH_LASTLOG)
59
# define LLOG_FILE _PATH_LASTLOG
61
# define LLOG_FILE "/usr/adm/lastlog"
67
# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
68
/* *BSD doesn't like a ':0' type entry in utmp */
75
# define TTYS_FILE "/etc/ttys"
80
# define UTL_PFX "xdm/"
81
# define UTL_OFF strlen(UTL_PFX)
88
crc32s(const char *str)
91
unsigned crc = 0xffffffff, by;
94
by = (crc & 255) ^ *(const unsigned char *)str;
95
for (b = 0; b < 8; b++)
96
by = (by >> 1) ^ (-(by & 1) & 0xedb88320);
97
crc = (crc >> 8) ^ by;
103
#if (!defined(NO_UTMP) && defined(BSD_UTMP)) || \
104
!defined(HAVE_UPDWTMP) || \
105
(!defined(NO_LASTLOG) && !defined(HAVE_LASTLOGX))
107
writeOut(int fd, const void *buf, size_t len, const char *msg)
110
if ((ret = write(fd, buf, len)) != (ssize_t)len) {
121
sessreg(struct display *d, int pid, const char *user, int uid)
123
const char *dot, *colon;
127
int utmp, slot, freeslot;
136
# ifdef HAVE_LASTLOGX
138
# define ll_time ll_tv.tv_sec
149
bzero(&ut_ent, sizeof(ut_ent));
152
strncpy(ut_ent.ut_user, user, sizeof(ut_ent.ut_user));
155
ut_ent.ut_type = USER_PROCESS;
157
ut_ent.ut_type = DEAD_PROCESS;
160
ut_ent.ut_time = time(0);
162
colon = strchr(d->name, ':');
163
clen = strlen(colon);
164
if (clen > (int)(sizeof(ut_ent.ut_line) - UTL_OFF) - 2)
165
return; /* uhm, well ... */
166
if (colon == d->name) {
168
strncpy(ut_ent.ut_id, d->name, sizeof(ut_ent.ut_id));
172
#ifdef HAVE_STRUCT_UTMP_UT_HOST
177
if (colon - d->name > (int)sizeof(ut_ent.ut_host)) {
178
ut_ent.ut_host[0] = '~';
179
memcpy(ut_ent.ut_host + 1,
180
colon - (sizeof(ut_ent.ut_host) - 1),
181
sizeof(ut_ent.ut_host) - 1);
183
memcpy(ut_ent.ut_host, d->name, colon - d->name);
188
crc = crc32s(d->name);
189
ut_ent.ut_id[0] = crc % 26 + 'A';
191
for (i = 1; i < sizeof(ut_ent.ut_id); i++) {
194
ut_ent.ut_id[i] = c < 26 ? c + 'A' :
195
c < 52 ? c - 26 + 'a' : c - 52 + '0';
198
left = sizeof(ut_ent.ut_line) - UTL_OFF - clen;
199
if (colon - d->name <= left) {
200
clen += colon - d->name;
204
dot = strchr(d->name, '.');
205
if (dot && dot - d->name < left) {
206
memcpy(ut_ent.ut_line + UTL_OFF, d->name, left - 1);
207
ut_ent.ut_line[UTL_OFF + left - 1] = '~';
209
memcpy(ut_ent.ut_line + UTL_OFF, d->name, left / 2 - 1);
210
ut_ent.ut_line[UTL_OFF + left/2 - 1] = '~';
212
memcpy(ut_ent.ut_line + UTL_OFF + left / 2,
213
dot - (left - left / 2 - 1),
214
left - left / 2 - 1);
215
ut_ent.ut_line[UTL_OFF + left - 1] = '~';
217
memcpy(ut_ent.ut_line + UTL_OFF + left / 2,
218
colon - (left - left / 2), left - left / 2);
223
memcpy(ut_ent.ut_line, UTL_PFX, UTL_OFF);
225
memcpy(ut_ent.ut_line + UTL_OFF + left, colon, clen);
229
if ((utmp = open(UTMP_FILE, O_RDWR)) < 0) {
230
debug("cannot open utmp file " UTMP_FILE ": %m\n");
235
if (!(ttys = fopen(TTYS_FILE, "r"))) {
236
logWarn("Cannot open tty file " TTYS_FILE ": %m\n");
239
while ((c = getc(ttys)) != EOF)
252
lseek(utmp, slot * sizeof(entry), SEEK_SET);
253
while (read(utmp, (char *)&entry, sizeof(entry)) == sizeof(entry)) {
254
if (!strncmp(entry.ut_line, ut_ent.ut_line,
255
sizeof(entry.ut_line)))
256
# ifdef HAVE_STRUCT_UTMP_UT_HOST
257
if (!strncmp(entry.ut_host, ut_ent.ut_host,
258
sizeof(entry.ut_host)))
261
if (freeslot < 0 && *entry.ut_user == '\0')
266
debug("utmp entry for display %s vanished\n", d->name);
274
# ifdef HAVE_STRUCT_UTMP_UT_HOST
276
bzero(ut_ent.ut_host, sizeof(ut_ent.ut_host));
278
lseek(utmp, slot * sizeof(ut_ent), SEEK_SET);
279
writeOut(utmp, &ut_ent, sizeof(ut_ent),
280
"Cannot write utmp file " UTMP_FILE ": %m\n");
285
PUTUTLINE(&ut_ent); /* Returns void on some systems => no error check. */
292
updwtmpx(WTMP_FILE, &ut_ent);
294
updwtmp(WTMP_FILE, &ut_ent);
297
if ((wtmp = open(WTMP_FILE, O_WRONLY | O_APPEND)) < 0)
298
debug("cannot open wtmp file " WTMP_FILE ": %m\n");
300
writeOut(wtmp, &ut_ent, sizeof(ut_ent),
301
"Cannot write wtmp file " WTMP_FILE ": %m\n");
306
bzero((char *)&ll, sizeof(ll));
307
ll.ll_time = ut_ent.ut_time;
308
memcpy(ll.ll_line, ut_ent.ut_line, sizeof(ll.ll_line));
309
memcpy(ll.ll_host, ut_ent.ut_host, sizeof(ll.ll_host));
310
# ifdef HAVE_LASTLOGX
311
updlastlogx(LLOG_FILE, uid, &ll);
313
if ((llog = open(LLOG_FILE, O_RDWR)) < 0) {
314
debug("cannot open lastlog file " LLOG_FILE ": %m\n");
316
lseek(llog, (off_t)uid * sizeof(ll), SEEK_SET);
317
writeOut(llog, &ll, sizeof(ll),
318
"Cannot write lastlog file " LLOG_FILE ": %m\n");
328
char tmp[sizeof("/dev/") + sizeof(ut_ent.ut_line)];
329
mkdir("/dev/" UTL_PFX, 0755);
330
chmod("/dev/" UTL_PFX, 0755);
331
sprintf(tmp, "/dev/%.*s", sizeof(ut_ent.ut_line), ut_ent.ut_line);
333
close(creat(tmp, 0644));