~ubuntu-branches/ubuntu/dapper/screen/dapper-updates

« back to all changes in this revision

Viewing changes to utmp.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathaniel McCallum
  • Date: 2004-09-03 15:15:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040903151533-px02yqlrchs4fv2t
Tags: upstream-4.0.2
ImportĀ upstreamĀ versionĀ 4.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1993-2002
 
2
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
 
3
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
 
4
 * Copyright (c) 1987 Oliver Laumann
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program (see the file COPYING); if not, write to the
 
18
 * Free Software Foundation, Inc.,
 
19
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 
20
 *
 
21
 ****************************************************************
 
22
 */
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <fcntl.h>
 
27
 
 
28
#include "config.h"
 
29
#include "screen.h"
 
30
#include "extern.h"
 
31
 
 
32
#ifdef HAVE_UTEMPTER
 
33
#include <utempter.h>
 
34
#endif
 
35
 
 
36
 
 
37
extern struct display *display;
 
38
#ifdef CAREFULUTMP
 
39
extern struct win *windows;
 
40
#endif
 
41
extern struct win *fore;
 
42
extern char *LoginName;
 
43
extern int real_uid, eff_uid;
 
44
 
 
45
 
 
46
/*
 
47
 *  UTNOKEEP: A (ugly) hack for apollo that does two things:
 
48
 *    1) Always close and reopen the utmp file descriptor. (I don't know
 
49
 *       for what reason this is done...)
 
50
 *    2) Implement an unsorted utmp file much like GETUTENT.
 
51
 *  (split into UT_CLOSE and UT_UNSORTED)
 
52
 */
 
53
 
 
54
 
 
55
#ifdef UTNOKEEP
 
56
# define UT_CLOSE
 
57
# define UT_UNSORTED
 
58
#endif
 
59
 
 
60
#ifdef UT_CLOSE
 
61
# undef UT_CLOSE
 
62
# define UT_CLOSE endutent()
 
63
#else
 
64
# define UT_CLOSE
 
65
#endif
 
66
 
 
67
 
 
68
/*
 
69
 *  we have a suid-root helper app that changes the utmp for us
 
70
 *  (won't work for login-slots)
 
71
 */
 
72
#if (defined(sun) && defined(SVR4) && defined(GETUTENT)) || defined(HAVE_UTEMPTER)
 
73
# define UTMP_HELPER
 
74
#endif
 
75
 
 
76
 
 
77
 
 
78
#ifdef UTMPOK
 
79
 
 
80
 
 
81
static slot_t TtyNameSlot __P((char *));
 
82
static void makeuser __P((struct utmp *, char *, char *, int));
 
83
static void makedead __P((struct utmp *));
 
84
static int  pututslot __P((slot_t, struct utmp *, char *, struct win *));
 
85
static struct utmp *getutslot __P((slot_t));
 
86
#ifndef GETUTENT
 
87
static struct utmp *getutent __P((void));
 
88
static void endutent __P((void));
 
89
static int  initutmp __P((void));
 
90
static void setutent __P((void));
 
91
#endif
 
92
#if defined(linux) && defined(GETUTENT)
 
93
static struct utmp *xpututline __P((struct utmp *utmp));
 
94
# define pututline xpututline
 
95
#endif
 
96
 
 
97
 
 
98
static int utmpok;
 
99
static char UtmpName[] = UTMPFILE;
 
100
#ifndef UTMP_HELPER
 
101
static int utmpfd = -1;
 
102
#endif
 
103
 
 
104
 
 
105
# if defined(GETUTENT) && (!defined(SVR4) || defined(__hpux))
 
106
#  if defined(hpux) /* cruel hpux release 8.0 */
 
107
#   define pututline _pututline
 
108
#  endif /* hpux */
 
109
extern struct utmp *getutline(), *pututline();
 
110
#  if defined(_SEQUENT_)
 
111
extern struct utmp *ut_add_user(), *ut_delete_user();
 
112
extern char *ut_find_host();
 
113
#   ifndef UTHOST
 
114
#    define UTHOST              /* _SEQUENT_ has ut_find_host() */
 
115
#   endif
 
116
#  endif /* _SEQUENT_ */
 
117
# endif /* GETUTENT && !SVR4 */
 
118
 
 
119
# if !defined(GETUTENT) && !defined(UT_UNSORTED)
 
120
#  ifdef GETTTYENT
 
121
#   include <ttyent.h>
 
122
#  else
 
123
struct ttyent { char *ty_name; };
 
124
static void           setttyent __P((void));
 
125
static struct ttyent *getttyent __P((void));
 
126
#  endif
 
127
# endif /* !GETUTENT && !UT_UNSORTED */
 
128
 
 
129
#ifndef _SEQUENT_
 
130
# undef  D_loginhost
 
131
# define D_loginhost D_utmp_logintty.ut_host
 
132
#endif
 
133
#ifndef UTHOST
 
134
# undef  D_loginhost
 
135
# define D_loginhost ((char *)0)
 
136
#endif
 
137
 
 
138
 
 
139
#endif /* UTMPOK */
 
140
 
 
141
 
 
142
/*
 
143
 * SlotToggle - modify the utmp slot of the fore window.
 
144
 *
 
145
 * how > 0      do try to set a utmp slot.
 
146
 * how = 0      try to withdraw a utmp slot.
 
147
 *
 
148
 * w_slot = -1  window not logged in.
 
149
 * w_slot = 0   window not logged in, but should be logged in. 
 
150
 *              (unable to write utmp, or detached).
 
151
 */
 
152
 
 
153
#ifndef UTMPOK
 
154
void
 
155
SlotToggle(how)
 
156
int how;
 
157
{
 
158
  debug1("SlotToggle (!UTMPOK) %d\n", how);
 
159
# ifdef UTMPFILE
 
160
  Msg(0, "Unable to modify %s.\n", UTMPFILE);
 
161
# else
 
162
  Msg(0, "Unable to modify utmp-database.\n");
 
163
# endif
 
164
}
 
165
#endif
 
166
 
 
167
 
 
168
 
 
169
#ifdef UTMPOK
 
170
 
 
171
void
 
172
SlotToggle(how)
 
173
int how;
 
174
{
 
175
  debug1("SlotToggle %d\n", how);
 
176
  if (fore->w_type != W_TYPE_PTY)
 
177
    {
 
178
      Msg(0, "Can only work with normal windows.\n");
 
179
      return;
 
180
    }
 
181
  if (how)
 
182
    {
 
183
      debug(" try to log in\n");
 
184
      if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0))
 
185
        {
 
186
#ifdef USRLIMIT
 
187
          if (CountUsers() >= USRLIMIT)
 
188
            {
 
189
              Msg(0, "User limit reached.");
 
190
              return;
 
191
            }
 
192
#endif
 
193
          if (SetUtmp(fore) == 0)
 
194
            Msg(0, "This window is now logged in.");
 
195
          else
 
196
            Msg(0, "This window should now be logged in.");
 
197
          WindowChanged(fore, 'f');
 
198
        }
 
199
      else
 
200
        Msg(0, "This window is already logged in.");
 
201
    }
 
202
  else
 
203
    {
 
204
      debug(" try to log out\n");
 
205
      if (fore->w_slot == (slot_t) -1)
 
206
        Msg(0, "This window is already logged out\n");
 
207
      else if (fore->w_slot == (slot_t) 0)
 
208
        {
 
209
          debug("What a relief! In fact, it was not logged in\n");
 
210
          Msg(0, "This window is not logged in.");
 
211
          fore->w_slot = (slot_t) -1;
 
212
        }
 
213
      else
 
214
        {
 
215
          RemoveUtmp(fore);
 
216
          if (fore->w_slot != (slot_t) -1)
 
217
            Msg(0, "What? Cannot remove Utmp slot?");
 
218
          else
 
219
            Msg(0, "This window is no longer logged in.");
 
220
#ifdef CAREFULUTMP
 
221
          CarefulUtmp();
 
222
#endif
 
223
          WindowChanged(fore, 'f');
 
224
        }
 
225
    }
 
226
}
 
227
 
 
228
 
 
229
#ifdef CAREFULUTMP
 
230
 
 
231
/* CAREFULUTMP: goodie for paranoid sysadmins: always leave one
 
232
 * window logged in
 
233
 */
 
234
void
 
235
CarefulUtmp()
 
236
{
 
237
  struct win *p;
 
238
 
 
239
  if (!windows)                 /* hopeless */
 
240
    return;
 
241
  debug("CarefulUtmp counting slots\n");
 
242
  for (p = windows; p; p = p->w_next)
 
243
    if (p->w_ptyfd >= 0 && p->w_slot != (slot_t)-1)
 
244
      return;                   /* found one, nothing to do */
 
245
 
 
246
  debug("CarefulUtmp: no slots, log one in again.\n");
 
247
  for (p = windows; p; p = p->w_next)
 
248
    if (p->w_ptyfd >= 0)        /* no zombies please */
 
249
      break;
 
250
  if (!p)
 
251
    return;                     /* really hopeless */
 
252
  SetUtmp(p);
 
253
  Msg(0, "Window %d is now logged in.\n", p->w_number);
 
254
}
 
255
#endif /* CAREFULUTMP */
 
256
 
 
257
 
 
258
void
 
259
InitUtmp()
 
260
{
 
261
  debug1("InitUtmp testing '%s'...\n", UtmpName);
 
262
#ifndef UTMP_HELPER
 
263
  if ((utmpfd = open(UtmpName, O_RDWR)) == -1)
 
264
    {
 
265
      if (errno != EACCES)
 
266
        Msg(errno, UtmpName);
 
267
      debug("InitUtmp failed.\n");
 
268
      utmpok = 0;
 
269
      return;
 
270
    }
 
271
# ifdef GETUTENT
 
272
  close(utmpfd);        /* it was just a test */
 
273
  utmpfd = -1;
 
274
# endif /* GETUTENT */
 
275
#endif  /* UTMP_HELPER */
 
276
  utmpok = 1;
 
277
}
 
278
 
 
279
 
 
280
#ifdef USRLIMIT
 
281
int
 
282
CountUsers()
 
283
{
 
284
  struct utmp *ut;
 
285
  int UserCount;
 
286
 
 
287
  debug1("CountUsers() - utmpok=%d\n", utmpok);
 
288
  if (!utmpok)
 
289
    return 0;
 
290
  UserCount = 0;
 
291
  setutent();
 
292
  while (ut = getutent())
 
293
    if (SLOT_USED(ut))
 
294
      UserCount++;
 
295
  UT_CLOSE;
 
296
  return UserCount;
 
297
}
 
298
#endif /* USRLIMIT */
 
299
 
 
300
 
 
301
 
 
302
/*
 
303
 * the utmp entry for tty is located and removed.
 
304
 * it is stored in D_utmp_logintty.
 
305
 */
 
306
void
 
307
RemoveLoginSlot()
 
308
{
 
309
  struct utmp u, *uu;
 
310
 
 
311
  ASSERT(display);
 
312
  debug("RemoveLoginSlot: removing your logintty\n");
 
313
  D_loginslot = TtyNameSlot(D_usertty);
 
314
  if (D_loginslot == (slot_t)0 || D_loginslot == (slot_t)-1)
 
315
    return;
 
316
#ifdef UTMP_HELPER
 
317
  if (eff_uid)  /* helpers can't do login slots. sigh. */
 
318
#else
 
319
  if (!utmpok)
 
320
#endif
 
321
    {
 
322
      D_loginslot = 0;
 
323
      debug("RemoveLoginSlot: utmpok == 0\n");
 
324
    }
 
325
  else
 
326
    {
 
327
#ifdef _SEQUENT_
 
328
      {
 
329
        char *p;
 
330
        if ((p = ut_find_host(D_loginslot)) != 0)
 
331
          strncpy(D_loginhost, p, sizeof(D_loginhost) - 1);
 
332
        D_loginhost[sizeof(D_loginhost) - 1] = 0;
 
333
      }
 
334
#endif /* _SEQUENT_ */
 
335
 
 
336
      if ((uu = getutslot(D_loginslot)) == 0)
 
337
        {
 
338
          debug("Utmp slot not found -> not removed");
 
339
          D_loginslot = 0;
 
340
        }
 
341
      else
 
342
        {
 
343
          D_utmp_logintty = *uu;
 
344
          u = *uu;
 
345
          makedead(&u);
 
346
          if (pututslot(D_loginslot, &u, (char *)0, (struct win *)0) == 0)
 
347
            D_loginslot = 0;
 
348
        }
 
349
      UT_CLOSE;
 
350
    }
 
351
  debug1(" slot %d zapped\n", (int)D_loginslot);
 
352
  if (D_loginslot == (slot_t)0)
 
353
    {
 
354
      /* couldn't remove slot, do a 'mesg n' at least. */
 
355
      struct stat stb;
 
356
      char *tty;
 
357
      debug("couln't zap slot -> do mesg n\n");
 
358
      D_loginttymode = 0;
 
359
      if ((tty = ttyname(D_userfd)) && stat(tty, &stb) == 0 && (int)stb.st_uid == real_uid && ((int)stb.st_mode & 0777) != 0666)
 
360
        {
 
361
          D_loginttymode = (int)stb.st_mode & 0777;
 
362
          chmod(D_usertty, stb.st_mode & 0600);
 
363
        }
 
364
    }
 
365
}
 
366
 
 
367
/*
 
368
 * D_utmp_logintty is reinserted into utmp
 
369
 */
 
370
void
 
371
RestoreLoginSlot()
 
372
{
 
373
  char *tty;
 
374
 
 
375
  debug("RestoreLoginSlot()\n");
 
376
  ASSERT(display);
 
377
  if (utmpok && D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1)
 
378
    {
 
379
      debug1(" logging you in again (slot %#x)\n", (int)D_loginslot);
 
380
      if (pututslot(D_loginslot, &D_utmp_logintty, D_loginhost, (struct win *)0) == 0)
 
381
        Msg(errno,"Could not write %s", UtmpName);
 
382
    }
 
383
  UT_CLOSE;
 
384
  D_loginslot = (slot_t)0;
 
385
  if (D_loginttymode && (tty = ttyname(D_userfd)))
 
386
    chmod(tty, D_loginttymode);
 
387
}
 
388
 
 
389
 
 
390
 
 
391
/*
 
392
 * Construct a utmp entry for window wi.
 
393
 * the hostname field reflects what we know about the user (display)
 
394
 * location. If d_loginhost is not set, then he is local and we write
 
395
 * down the name of his terminal line; else he is remote and we keep
 
396
 * the hostname here. The letter S and the window id will be appended.
 
397
 * A saved utmp entry in wi->w_savut serves as a template, usually.
 
398
 */ 
 
399
 
 
400
int
 
401
SetUtmp(wi)
 
402
struct win *wi;
 
403
{
 
404
  register slot_t slot;
 
405
  struct utmp u;
 
406
  int saved_ut;
 
407
#ifdef UTHOST
 
408
  char *p;
 
409
  char host[sizeof(D_loginhost) + 15];
 
410
#else
 
411
  char *host = 0;
 
412
#endif /* UTHOST */
 
413
 
 
414
  wi->w_slot = (slot_t)0;
 
415
  if (!utmpok || wi->w_type != W_TYPE_PTY)
 
416
    return -1;
 
417
  if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t)0)
 
418
    {
 
419
      debug1("SetUtmp failed (tty %s).\n",wi->w_tty);
 
420
      return -1;
 
421
    }
 
422
  debug2("SetUtmp %d will get slot %d...\n", wi->w_number, (int)slot);
 
423
 
 
424
  bzero((char *)&u, sizeof(u));
 
425
  if ((saved_ut = bcmp((char *) &wi->w_savut, (char *)&u, sizeof(u))))
 
426
    /* restore original, of which we will adopt all fields but ut_host */
 
427
    bcopy((char *)&wi->w_savut, (char *) &u, sizeof(u));
 
428
 
 
429
  if (!saved_ut)
 
430
    makeuser(&u, stripdev(wi->w_tty), LoginName, wi->w_pid);
 
431
 
 
432
#ifdef UTHOST
 
433
  host[sizeof(host) - 15] = '\0';
 
434
  if (display)
 
435
    {
 
436
      strncpy(host, D_loginhost, sizeof(host) - 15);
 
437
      if (D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1 && host[0] != '\0')
 
438
        {
 
439
          /*
 
440
           * we want to set our ut_host field to something like
 
441
           * ":ttyhf:s.0" or
 
442
           * "faui45:s.0" or
 
443
           * "132.199.81.4:s.0" (even this may hurt..), but not
 
444
           * "faui45.informati"......:s.0
 
445
           * HPUX uses host:0.0, so chop at "." and ":" (Eric Backus)
 
446
           */
 
447
          for (p = host; *p; p++)
 
448
            if ((*p < '0' || *p > '9') && (*p != '.'))
 
449
              break;
 
450
          if (*p)
 
451
            {
 
452
              for (p = host; *p; p++)
 
453
                if (*p == '.' || (*p == ':' && p != host))
 
454
                  {
 
455
                    *p = '\0';
 
456
                    break;
 
457
                  }
 
458
            }
 
459
        }
 
460
      else
 
461
        {
 
462
          strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 15 - 1);
 
463
          host[0] = ':';
 
464
        }
 
465
    }
 
466
  else
 
467
    strncpy(host, "local", sizeof(host) - 15);
 
468
 
 
469
  sprintf(host + strlen(host), ":S.%d", wi->w_number);
 
470
  debug1("rlogin hostname: '%s'\n", host);
 
471
 
 
472
# if !defined(_SEQUENT_) && !defined(sequent)
 
473
  strncpy(u.ut_host, host, sizeof(u.ut_host));
 
474
# endif
 
475
#endif /* UTHOST */
 
476
 
 
477
  if (pututslot(slot, &u, host, wi) == 0)
 
478
    {
 
479
      Msg(errno,"Could not write %s", UtmpName);
 
480
      UT_CLOSE;
 
481
      return -1;
 
482
    }
 
483
  debug("SetUtmp successful\n");
 
484
  wi->w_slot = slot;
 
485
  bcopy((char *)&u, (char *)&wi->w_savut, sizeof(u));
 
486
  UT_CLOSE;
 
487
  return 0;
 
488
}
 
489
 
 
490
/*
 
491
 * if slot could be removed or was 0,  wi->w_slot = -1;
 
492
 * else not changed.
 
493
 */
 
494
 
 
495
int
 
496
RemoveUtmp(wi)
 
497
struct win *wi;
 
498
{
 
499
  struct utmp u, *uu;
 
500
  slot_t slot;
 
501
 
 
502
  slot = wi->w_slot;
 
503
  debug1("RemoveUtmp slot=%#x\n", slot);
 
504
  if (!utmpok)
 
505
    return -1;
 
506
  if (slot == (slot_t)0 || slot == (slot_t)-1)
 
507
    {
 
508
      wi->w_slot = (slot_t)-1;
 
509
      return 0;
 
510
    }
 
511
  bzero((char *) &u, sizeof(u));
 
512
#ifdef sgi
 
513
  bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u));
 
514
  uu  = &u;
 
515
#else
 
516
  if ((uu = getutslot(slot)) == 0)
 
517
    {
 
518
      Msg(0, "Utmp slot not found -> not removed");
 
519
      return -1;
 
520
    }
 
521
  bcopy((char *)uu, (char *)&wi->w_savut, sizeof(wi->w_savut));
 
522
#endif
 
523
  u = *uu;
 
524
  makedead(&u);
 
525
  if (pututslot(slot, &u, (char *)0, wi) == 0)
 
526
    {
 
527
      Msg(errno,"Could not write %s", UtmpName);
 
528
      UT_CLOSE;
 
529
      return -1;
 
530
    }
 
531
  debug("RemoveUtmp successfull\n");
 
532
  wi->w_slot = (slot_t)-1;
 
533
  UT_CLOSE;
 
534
  return 0;
 
535
}
 
536
 
 
537
 
 
538
 
 
539
/*********************************************************************
 
540
 *
 
541
 *  routines using the getut* api
 
542
 */
 
543
 
 
544
#ifdef GETUTENT
 
545
 
 
546
#define SLOT_USED(u) (u->ut_type == USER_PROCESS)
 
547
 
 
548
static struct utmp *
 
549
getutslot(slot)
 
550
slot_t slot;
 
551
{
 
552
  struct utmp u;
 
553
  bzero((char *)&u, sizeof(u));
 
554
  strncpy(u.ut_line, slot, sizeof(u.ut_line));
 
555
  setutent();
 
556
  return getutline(&u);
 
557
}
 
558
 
 
559
static int
 
560
pututslot(slot, u, host, wi)
 
561
slot_t slot;
 
562
struct utmp *u;
 
563
char *host;
 
564
struct win *wi;
 
565
{
 
566
#ifdef _SEQUENT_
 
567
  if (SLOT_USED(u) && host && *host)
 
568
    return ut_add_user(u.ut_name, slot, u.ut_pid, host) != 0;
 
569
  if (!SLOT_USED(u))
 
570
    return ut_delete_user(slot, u.ut_pid, 0, 0) != 0;
 
571
#endif
 
572
#ifdef HAVE_UTEMPTER
 
573
  if (eff_uid && wi->w_ptyfd != -1)
 
574
    {
 
575
      /* sigh, linux hackers made the helper functions void */
 
576
      if (SLOT_USED(u))
 
577
        addToUtmp(wi->w_tty, host, wi->w_ptyfd);
 
578
      else
 
579
        removeLineFromUtmp(wi->w_tty, wi->w_ptyfd);
 
580
      return 1; /* pray for success */
 
581
    }
 
582
#endif
 
583
  setutent();
 
584
  return pututline(u) != 0;
 
585
}
 
586
 
 
587
static void
 
588
makedead(u)
 
589
struct utmp *u;
 
590
{
 
591
  u->ut_type = DEAD_PROCESS;
 
592
#if !defined(linux) || defined(EMPTY)
 
593
  u->ut_exit.e_termination = 0;
 
594
  u->ut_exit.e_exit = 0;
 
595
#endif
 
596
#if !defined(sun) || !defined(SVR4)
 
597
  u->ut_user[0] = 0;    /* for Digital UNIX, kilbi@rad.rwth-aachen.de */
 
598
#endif
 
599
}
 
600
 
 
601
static void
 
602
makeuser(u, line, user, pid)
 
603
struct utmp *u;
 
604
char *line, *user;
 
605
int pid;
 
606
{
 
607
  u->ut_type = USER_PROCESS;
 
608
  strncpy(u->ut_user, user, sizeof(u->ut_user));
 
609
  /* Now the tricky part... guess ut_id */
 
610
#if defined(sgi) || defined(linux)
 
611
  strncpy(u->ut_id, line + 3, sizeof(u->ut_id));
 
612
#else /* sgi */
 
613
# ifdef _IBMR2
 
614
  strncpy(u->ut_id, line, sizeof(u->ut_id));
 
615
# else
 
616
  strncpy(u->ut_id, line + strlen(line) - 2, sizeof(u->ut_id));
 
617
# endif
 
618
#endif /* sgi */
 
619
  strncpy(u->ut_line, line, sizeof(u->ut_line));
 
620
  u->ut_pid = pid;
 
621
  (void)time((time_t *)&u->ut_time);
 
622
}
 
623
 
 
624
static slot_t
 
625
TtyNameSlot(nam)
 
626
char *nam;
 
627
{
 
628
  return stripdev(nam);
 
629
}
 
630
 
 
631
 
 
632
#else /* GETUTENT */
 
633
 
 
634
/*********************************************************************
 
635
 *
 
636
 *  getut emulation for systems lacking the api
 
637
 */
 
638
 
 
639
static struct utmp uent;
 
640
 
 
641
#define SLOT_USED(u) (u.ut_name[0] != 0)
 
642
 
 
643
static int
 
644
initutmp()
 
645
{
 
646
  if (utmpfd >= 0)
 
647
    return 1;
 
648
  return (utmpfd = open(UtmpName, O_RDWR)) >= 0;
 
649
}
 
650
 
 
651
static void
 
652
setutent()
 
653
{
 
654
  if (utmpfd >= 0)
 
655
    (void)lseek(utmpfd, (off_t)0, 0);
 
656
}
 
657
 
 
658
static void
 
659
endutent()
 
660
{
 
661
  if (utmpfd >= 0)
 
662
    close(utmpfd);
 
663
  utmpfd = -1;
 
664
}
 
665
 
 
666
static struct utmp *
 
667
getutent()
 
668
{
 
669
  if (utmpfd < 0 && !initutmp())
 
670
    return 0;
 
671
  if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent))
 
672
    return 0;
 
673
  return &uent;
 
674
}
 
675
 
 
676
static struct utmp *
 
677
getutslot(slot)
 
678
slot_t slot;
 
679
{
 
680
  if (utmpfd < 0 && !initutmp())
 
681
    return 0;
 
682
  lseek(utmpfd, (off_t)(slot * sizeof(struct utmp)), 0);
 
683
  if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent))
 
684
    return 0;
 
685
  return &uent;
 
686
}
 
687
 
 
688
static int
 
689
pututslot(slot, u, host, wi)
 
690
slot_t slot;
 
691
struct utmp *u;
 
692
char *host;
 
693
struct win *wi;
 
694
{
 
695
#ifdef sequent
 
696
  if (SLOT_USED(u))
 
697
    return add_utmp(slot, u) != -1;
 
698
#endif
 
699
  if (utmpfd < 0 && !initutmp())
 
700
    return 0;
 
701
  lseek(utmpfd, (off_t)(slot * sizeof(*u)), 0);
 
702
  if (write(utmpfd, u, sizeof(*u)) != sizeof(*u))
 
703
    return 0;
 
704
  return 1;
 
705
}
 
706
 
 
707
 
 
708
static void
 
709
makedead(u)
 
710
struct utmp *u;
 
711
{
 
712
#ifdef UT_UNSORTED
 
713
  bzero(u->ut_name, sizeof(u->ut_name));
 
714
# ifdef UTHOST
 
715
  bzero(u->ut_host, sizeof(u->ut_host));
 
716
# endif
 
717
#else
 
718
  bzero((char *)u, sizeof(*u));
 
719
#endif
 
720
}
 
721
 
 
722
 
 
723
static void
 
724
makeuser(u, line, user, pid)
 
725
struct utmp *u;
 
726
char *line, *user;
 
727
int pid;
 
728
{
 
729
  strncpy(u->ut_line, line, sizeof(u->ut_line));
 
730
  strncpy(u->ut_name, user, sizeof(u->ut_name));
 
731
  (void)time((time_t *)&u->ut_time);
 
732
}
 
733
 
 
734
static slot_t
 
735
TtyNameSlot(nam)
 
736
char *nam;
 
737
{
 
738
  slot_t slot;
 
739
  char *line;
 
740
#ifndef UT_UNSORTED
 
741
  struct ttyent *tp;
 
742
#endif
 
743
 
 
744
  line = stripdev(nam);
 
745
#ifdef UT_UNSORTED
 
746
  setutent();
 
747
  if (utmpfd < 0)
 
748
    return -1;
 
749
  for (slot = 0; getutent(); slot++)
 
750
    if (strcmp(uent.ut_line, line) == 0)
 
751
      break;
 
752
  UT_CLOSE;
 
753
#else
 
754
  slot = 1;
 
755
  setttyent();
 
756
  while ((tp = getttyent()) != 0 && strcmp(line, tp->ty_name) != 0)
 
757
    slot++;
 
758
#endif
 
759
  return slot;
 
760
}
 
761
 
 
762
#endif  /* GETUTENT */
 
763
 
 
764
 
 
765
 
 
766
/*********************************************************************
 
767
 *
 
768
 *  Cheap plastic imitation of ttyent routines.
 
769
 */
 
770
 
 
771
#if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED)
 
772
 
 
773
 
 
774
static char *tt, *ttnext;
 
775
static char ttys[] = "/etc/ttys";
 
776
 
 
777
static void
 
778
setttyent()
 
779
{
 
780
  if (ttnext == 0)
 
781
    {
 
782
      struct stat s;
 
783
      register int f;
 
784
      register char *p, *ep;
 
785
 
 
786
      if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1)
 
787
        Panic(errno, ttys);
 
788
      if ((tt = malloc((unsigned) s.st_size + 1)) == 0)
 
789
        Panic(0, strnomem);
 
790
      if (read(f, tt, s.st_size) != s.st_size)
 
791
        Panic(errno, ttys);
 
792
      close(f);
 
793
      for (p = tt, ep = p + s.st_size; p < ep; p++)
 
794
        if (*p == '\n')
 
795
          *p = '\0';
 
796
      *p = '\0';
 
797
    }
 
798
  ttnext = tt;
 
799
}
 
800
 
 
801
static struct ttyent *
 
802
getttyent()
 
803
{
 
804
  static struct ttyent t;
 
805
 
 
806
  if (*ttnext == '\0')
 
807
    return NULL;
 
808
  t.ty_name = ttnext + 2;
 
809
  ttnext += strlen(ttnext) + 1;
 
810
  return &t;
 
811
}
 
812
 
 
813
#endif  /* !GETTTYENT && !GETUTENT && !UT_UNSORTED*/
 
814
 
 
815
 
 
816
 
 
817
#endif /* UTMPOK */
 
818
 
 
819
 
 
820
 
 
821
 
 
822
/*********************************************************************
 
823
 *
 
824
 *  getlogin() replacement (for SVR4 machines)
 
825
 */
 
826
 
 
827
# if defined(BUGGYGETLOGIN) && defined(UTMP_FILE)
 
828
char *
 
829
getlogin()
 
830
{
 
831
  char *tty = NULL;
 
832
#ifdef utmp
 
833
# undef utmp
 
834
#endif
 
835
  struct utmp u;
 
836
  static char retbuf[sizeof(u.ut_user)+1];
 
837
  int fd;
 
838
 
 
839
  for (fd = 0; fd <= 2 && (tty = ttyname(fd)) == NULL; fd++)
 
840
    ;
 
841
  if ((tty == NULL) || ((fd = open(UTMP_FILE, O_RDONLY)) < 0))
 
842
    return NULL;
 
843
  tty = stripdev(tty);
 
844
  retbuf[0] = '\0';
 
845
  while (read(fd, (char *)&u, sizeof(struct utmp)) == sizeof(struct utmp))
 
846
    {
 
847
      if (!strncmp(tty, u.ut_line, sizeof(u.ut_line)))
 
848
        {
 
849
          strncpy(retbuf, u.ut_user, sizeof(u.ut_user));
 
850
          retbuf[sizeof(u.ut_user)] = '\0';
 
851
          if (u.ut_type == USER_PROCESS)
 
852
            break;
 
853
        }
 
854
    }
 
855
  close(fd);
 
856
 
 
857
  return *retbuf ? retbuf : NULL;
 
858
}
 
859
# endif /* BUGGYGETLOGIN */
 
860
 
 
861
#if defined(linux) && defined(GETUTENT)
 
862
# undef pututline
 
863
 
 
864
/* aargh, linux' pututline returns void! */
 
865
struct utmp *
 
866
xpututline(u)
 
867
struct utmp *u;
 
868
{
 
869
  struct utmp *u2;
 
870
  pututline(u);
 
871
  setutent();
 
872
  u2 = getutline(u);
 
873
  if (u2 == 0)
 
874
    return u->ut_type == DEAD_PROCESS ? u : 0;
 
875
  return u->ut_type == u2->ut_type ? u : 0;
 
876
}
 
877
#endif
 
878