~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kdm/backend/sessreg.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright 1990, 1998  The Open Group
 
4
Copyright 2005 Oswald Buddenhagen <ossi@kde.org>
 
5
 
 
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
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
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.
 
22
 
 
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
 
26
from The Open Group.
 
27
 
 
28
*/
 
29
 
 
30
/*
 
31
 
 
32
  Author: Keith Packard, MIT X Consortium
 
33
  Lastlog support and dynamic utmp entry allocation
 
34
    by Andreas Stolcke <stolcke@icsi.berkeley.edu>
 
35
 
 
36
*/
 
37
 
 
38
#define _FILE_OFFSET_BITS 64
 
39
#include "dm.h"
 
40
#include "dm_error.h"
 
41
 
 
42
#if defined(__svr4__) || defined(__Lynx__) || defined(__QNX__) || defined(__APPLE__) || defined(_SEQUENT_) /*|| defined(USE_PAM)*/
 
43
# define NO_LASTLOG
 
44
#endif
 
45
#ifdef __FreeBSD__
 
46
# if __FreeBSD_version >= 900007
 
47
#  define NO_LASTLOG
 
48
# endif
 
49
#endif
 
50
 
 
51
#ifndef NO_LASTLOG
 
52
# ifdef HAVE_LASTLOG_H
 
53
#  include <lastlog.h>
 
54
# endif
 
55
# ifndef LLOG_FILE
 
56
#  ifdef _PATH_LASTLOGX
 
57
#   define LLOG_FILE _PATH_LASTLOGX
 
58
#  elif defined(_PATH_LASTLOG)
 
59
#   define LLOG_FILE _PATH_LASTLOG
 
60
#  else
 
61
#   define LLOG_FILE "/usr/adm/lastlog"
 
62
#  endif
 
63
# endif
 
64
#endif
 
65
 
 
66
#ifdef BSD
 
67
# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
 
68
/* *BSD doesn't like a ':0' type entry in utmp */
 
69
#  define NO_UTMP
 
70
# endif
 
71
#endif
 
72
 
 
73
#ifdef BSD_UTMP
 
74
# ifndef TTYS_FILE
 
75
#  define TTYS_FILE "/etc/ttys"
 
76
# endif
 
77
#endif
 
78
 
 
79
#ifdef _AIX
 
80
# define UTL_PFX "xdm/"
 
81
# define UTL_OFF strlen(UTL_PFX)
 
82
#else
 
83
# define UTL_OFF 0
 
84
#endif
 
85
 
 
86
#ifndef BSD_UTMP
 
87
static unsigned
 
88
crc32s(const char *str)
 
89
{
 
90
    int b;
 
91
    unsigned crc = 0xffffffff, by;
 
92
 
 
93
    for (; *str; str++) {
 
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;
 
98
    }
 
99
    return crc;
 
100
}
 
101
#endif
 
102
 
 
103
#if (!defined(NO_UTMP) && defined(BSD_UTMP)) || \
 
104
    !defined(HAVE_UPDWTMP) || \
 
105
    (!defined(NO_LASTLOG) && !defined(HAVE_LASTLOGX))
 
106
static void
 
107
writeOut(int fd, const void *buf, size_t len, const char *msg)
 
108
{
 
109
    ssize_t ret;
 
110
    if ((ret = write(fd, buf, len)) != (ssize_t)len) {
 
111
        if (ret >= 0)
 
112
            errno = -ENOSPC;
 
113
        logError(msg);
 
114
    }
 
115
    if (close(fd) < 0)
 
116
        logError(msg);
 
117
}
 
118
#endif
 
119
 
 
120
void
 
121
sessreg(struct display *d, int pid, const char *user, int uid)
 
122
{
 
123
    const char *dot, *colon;
 
124
    int left, clen, c;
 
125
#ifdef BSD_UTMP
 
126
    FILE *ttys;
 
127
    int utmp, slot, freeslot;
 
128
    STRUCTUTMP entry;
 
129
#else
 
130
    unsigned crc, i;
 
131
#endif
 
132
#ifndef HAVE_UPDWTMP
 
133
    int wtmp;
 
134
#endif
 
135
#ifndef NO_LASTLOG
 
136
# ifdef HAVE_LASTLOGX
 
137
    struct lastlogx ll;
 
138
#  define ll_time ll_tv.tv_sec
 
139
# else
 
140
    int llog;
 
141
    struct lastlog ll;
 
142
# endif
 
143
#endif
 
144
    STRUCTUTMP ut_ent;
 
145
 
 
146
    if (!d->useSessReg)
 
147
        return;
 
148
 
 
149
    bzero(&ut_ent, sizeof(ut_ent));
 
150
 
 
151
    if (pid) {
 
152
        strncpy(ut_ent.ut_user, user, sizeof(ut_ent.ut_user));
 
153
#ifndef BSD_UTMP
 
154
        ut_ent.ut_pid = pid;
 
155
        ut_ent.ut_type = USER_PROCESS;
 
156
    } else {
 
157
        ut_ent.ut_type = DEAD_PROCESS;
 
158
#endif
 
159
    }
 
160
    ut_ent.ut_time = time(0);
 
161
 
 
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) {
 
167
#ifndef BSD_UTMP
 
168
        strncpy(ut_ent.ut_id, d->name, sizeof(ut_ent.ut_id));
 
169
#endif
 
170
        left = 0;
 
171
    } else {
 
172
#ifdef HAVE_STRUCT_UTMP_UT_HOST
 
173
# ifndef BSD_UTMP
 
174
        if (pid)
 
175
# endif
 
176
        {
 
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);
 
182
            } else {
 
183
                memcpy(ut_ent.ut_host, d->name, colon - d->name);
 
184
            }
 
185
        }
 
186
#endif
 
187
#ifndef BSD_UTMP
 
188
        crc = crc32s(d->name);
 
189
        ut_ent.ut_id[0] = crc % 26 + 'A';
 
190
        crc /= 26;
 
191
        for (i = 1; i < sizeof(ut_ent.ut_id); i++) {
 
192
            c = crc % 62;
 
193
            crc /= 62;
 
194
            ut_ent.ut_id[i] = c < 26 ? c + 'A' :
 
195
                              c < 52 ? c - 26 + 'a' : c - 52 + '0';
 
196
        }
 
197
#endif
 
198
        left = sizeof(ut_ent.ut_line) - UTL_OFF - clen;
 
199
        if (colon - d->name <= left) {
 
200
            clen += colon - d->name;
 
201
            colon = d->name;
 
202
            left = 0;
 
203
        } else {
 
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] = '~';
 
208
            } else {
 
209
                memcpy(ut_ent.ut_line + UTL_OFF, d->name, left / 2 - 1);
 
210
                ut_ent.ut_line[UTL_OFF + left/2 - 1] = '~';
 
211
                if (dot) {
 
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] = '~';
 
216
                } else
 
217
                    memcpy(ut_ent.ut_line + UTL_OFF + left / 2,
 
218
                           colon - (left - left / 2), left - left / 2);
 
219
            }
 
220
        }
 
221
    }
 
222
#ifdef UTL_PFX
 
223
    memcpy(ut_ent.ut_line, UTL_PFX, UTL_OFF);
 
224
#endif
 
225
    memcpy(ut_ent.ut_line + UTL_OFF + left, colon, clen);
 
226
 
 
227
#ifndef NO_UTMP
 
228
# ifdef BSD_UTMP
 
229
    if ((utmp = open(UTMP_FILE, O_RDWR)) < 0) {
 
230
        debug("cannot open utmp file " UTMP_FILE ": %m\n");
 
231
    } else {
 
232
 
 
233
        slot = 1;
 
234
        if (pid) {
 
235
            if (!(ttys = fopen(TTYS_FILE, "r"))) {
 
236
                logWarn("Cannot open tty file " TTYS_FILE ": %m\n");
 
237
            } else {
 
238
                int column0 = True;
 
239
                while ((c = getc(ttys)) != EOF)
 
240
                    if (c == '\n') {
 
241
                        slot++;
 
242
                        column0 = True;
 
243
                    } else {
 
244
                        column0 = False;
 
245
                    }
 
246
                if (!column0)
 
247
                    slot++;
 
248
                fclose(ttys);
 
249
            }
 
250
        }
 
251
        freeslot = -1;
 
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)))
 
259
#  endif
 
260
                    goto found;
 
261
            if (freeslot < 0 && *entry.ut_user == '\0')
 
262
                freeslot = slot;
 
263
            slot++;
 
264
        }
 
265
        if (!pid) {
 
266
            debug("utmp entry for display %s vanished\n", d->name);
 
267
            close(utmp);
 
268
            goto skip;
 
269
        }
 
270
        if (freeslot >= 0)
 
271
            slot = freeslot;
 
272
      found:
 
273
 
 
274
#  ifdef HAVE_STRUCT_UTMP_UT_HOST
 
275
        if (!pid)
 
276
            bzero(ut_ent.ut_host, sizeof(ut_ent.ut_host));
 
277
#  endif
 
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");
 
281
    }
 
282
  skip:
 
283
# else
 
284
    SETUTENT();
 
285
    PUTUTLINE(&ut_ent); /* Returns void on some systems => no error check. */
 
286
    ENDUTENT();
 
287
# endif
 
288
#endif
 
289
 
 
290
#ifdef HAVE_UPDWTMP
 
291
# ifdef HAVE_UTMPX
 
292
    updwtmpx(WTMP_FILE, &ut_ent);
 
293
# else
 
294
    updwtmp(WTMP_FILE, &ut_ent);
 
295
# endif
 
296
#else
 
297
    if ((wtmp = open(WTMP_FILE, O_WRONLY | O_APPEND)) < 0)
 
298
        debug("cannot open wtmp file " WTMP_FILE ": %m\n");
 
299
    else
 
300
        writeOut(wtmp, &ut_ent, sizeof(ut_ent),
 
301
                 "Cannot write wtmp file " WTMP_FILE ": %m\n");
 
302
#endif
 
303
 
 
304
#ifndef NO_LASTLOG
 
305
    if (pid) {
 
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);
 
312
# else
 
313
        if ((llog = open(LLOG_FILE, O_RDWR)) < 0) {
 
314
            debug("cannot open lastlog file " LLOG_FILE ": %m\n");
 
315
        } else {
 
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");
 
319
        }
 
320
# endif
 
321
    }
 
322
#else
 
323
    (void)uid;
 
324
#endif
 
325
 
 
326
#ifdef UTL_PFX
 
327
    {
 
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);
 
332
        if (pid)
 
333
            close(creat(tmp, 0644));
 
334
        else
 
335
            unlink(tmp);
 
336
    }
 
337
#endif
 
338
}