summaryrefslogtreecommitdiff
path: root/utmp.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:23 +0200
committerAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:23 +0200
commitbdf45bc45637eefdbdee913465729f9d31d6c255 (patch)
tree9b6538c483ad6c2b38177068d5c5730397c9f292 /utmp.c
parent14a4b00c9ef680b78469333291270e4c276f100d (diff)
downloadscreen-bdf45bc45637eefdbdee913465729f9d31d6c255.tar.gz
Imported Upstream version 3.9.5upstream/3.9.5
Diffstat (limited to 'utmp.c')
-rw-r--r--utmp.c827
1 files changed, 446 insertions, 381 deletions
diff --git a/utmp.c b/utmp.c
index befe6cb..2a172d4 100644
--- a/utmp.c
+++ b/utmp.c
@@ -25,20 +25,6 @@
RCS_ID("$Id: utmp.c,v 1.7 1994/05/31 12:33:21 mlschroe Exp $ FAU")
-/*
- * An explanation of some weird things:
- *
- * linux should have GETUTENT, but their pututline() doesn't have
- * a return value.
- *
- * UTNOKEEP: A (ugly) hack for apollo that does two things:
- * 1) Always close and reopen the utmp file descriptor. (I don't know
- * for what reason this is done...)
- * 2) Implement an unsorted utmp file much like GETUTENT.
- * (split into UT_CLOSE and UT_UNSORTED)
- */
-
-
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -47,13 +33,19 @@ RCS_ID("$Id: utmp.c,v 1.7 1994/05/31 12:33:21 mlschroe Exp $ FAU")
#include "screen.h"
#include "extern.h"
-
extern struct display *display;
extern struct win *fore;
extern char *LoginName;
-#ifdef NETHACK
-extern nethackflag;
-#endif
+extern int real_uid, eff_uid;
+
+
+/*
+ * UTNOKEEP: A (ugly) hack for apollo that does two things:
+ * 1) Always close and reopen the utmp file descriptor. (I don't know
+ * for what reason this is done...)
+ * 2) Implement an unsorted utmp file much like GETUTENT.
+ * (split into UT_CLOSE and UT_UNSORTED)
+ */
#ifdef UTNOKEEP
@@ -61,16 +53,52 @@ extern nethackflag;
# define UT_UNSORTED
#endif
+#ifdef UT_CLOSE
+# undef UT_CLOSE
+# define UT_CLOSE endutent()
+#else
+# define UT_CLOSE
+#endif
+
+
+/*
+ * we have a suid-root helper app that changes the utmp for us
+ * (won't work for login-slots)
+ */
+#if (defined(sun) && defined(SVR4) && defined(GETUTENT)) || defined(HAVE_UTEMPTER)
+# define UTMP_HELPER
+#endif
+
+
#ifdef UTMPOK
+
static slot_t TtyNameSlot __P((char *));
+static void makeuser __P((struct utmp *, char *, char *, int));
+static void makedead __P((struct utmp *));
+static int pututslot __P((slot_t, struct utmp *, char *, struct win *));
+static struct utmp *getutslot __P((slot_t));
+#ifndef GETUTENT
+static struct utmp *getutent __P((void));
+static void endutent __P((void));
+static int initutmp __P((void));
+static void setutent __P((void));
+#endif
+#if defined(linux) && defined(GETUTENT)
+static struct utmp *xpututline __P((struct utmp *utmp));
+# define pututline xpututline
+#endif
+
-static int utmpok, utmpfd = -1;
+static int utmpok;
static char UtmpName[] = UTMPFILE;
+#ifndef UTMP_HELPER
+static int utmpfd = -1;
+#endif
-# if defined(GETUTENT) && !defined(SVR4)
+# if defined(GETUTENT) && (!defined(SVR4) || defined(__hpux))
# if defined(hpux) /* cruel hpux release 8.0 */
# define pututline _pututline
# endif /* hpux */
@@ -79,7 +107,7 @@ extern struct utmp *getutline(), *pututline();
extern struct utmp *ut_add_user(), *ut_delete_user();
extern char *ut_find_host();
# ifndef UTHOST
-# define UTHOST /* _SEQUENT_ has got ut_find_host() */
+# define UTHOST /* _SEQUENT_ has ut_find_host() */
# endif
# endif /* _SEQUENT_ */
# endif /* GETUTENT && !SVR4 */
@@ -94,9 +122,17 @@ static struct ttyent *getttyent __P((void));
# endif
# endif /* !GETUTENT && !UT_UNSORTED */
-#endif /* UTMPOK */
+#ifndef _SEQUENT_
+# undef D_loginhost
+# define D_loginhost D_utmp_logintty.ut_host
+#endif
+#ifndef UTHOST
+# undef D_loginhost
+# define D_loginhost ((char *)0)
+#endif
+#endif /* UTMPOK */
/*
@@ -109,28 +145,51 @@ static struct ttyent *getttyent __P((void));
* w_slot = 0 window not logged in, but should be logged in.
* (unable to write utmp, or detached).
*/
+
+#ifndef UTMPOK
void
SlotToggle(how)
int how;
{
- debug1("SlotToggle %d\n", how);
+ debug1("SlotToggle (!UTMPOK) %d\n", how);
+# ifdef UTMPFILE
+ Msg(0, "Unable to modify %s.\n", UTMPFILE);
+# else
+ Msg(0, "Unable to modify utmp-database.\n");
+# endif
+}
+#endif
+
+
+
#ifdef UTMPOK
+
+void
+SlotToggle(how)
+int how;
+{
+ debug1("SlotToggle %d\n", how);
+ if (fore->w_type != W_TYPE_PTY)
+ {
+ Msg(0, "Can only work with normal windows.\n");
+ return;
+ }
if (how)
{
debug(" try to log in\n");
if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0))
{
-# ifdef USRLIMIT
+#ifdef USRLIMIT
if (CountUsers() >= USRLIMIT)
- Msg(0, "User limit reached.");
- else
-# endif
- {
- if (SetUtmp(fore) == 0)
- Msg(0, "This window is now logged in.");
- else
- Msg(0, "This window should now be logged in.");
- }
+ {
+ Msg(0, "User limit reached.");
+ return;
+ }
+#endif
+ if (SetUtmp(fore) == 0)
+ Msg(0, "This window is now logged in.");
+ else
+ Msg(0, "This window should now be logged in.");
}
else
Msg(0, "This window is already logged in.");
@@ -153,28 +212,48 @@ int how;
Msg(0, "What? Cannot remove Utmp slot?");
else
Msg(0, "This window is no longer logged in.");
+#ifdef CAREFULUTMP
+ CarefulUtmp();
+#endif
}
}
-#else /* !UTMPOK */
-# ifdef UTMPFILE
- Msg(0, "Unable to modify %s.\n", UTMPFILE);
-# else
- Msg(0, "Unable to modify utmp-database.\n");
-# endif
-#endif
}
+#ifdef CAREFULUTMP
+/* CAREFULUTMP: goodie for paranoid sysadmins: always leave one
+ * window logged in
+ */
+void
+CarefulUtmp()
+{
+ struct win *p;
-#ifdef UTMPOK
-
+ if (!windows) /* hopeless */
+ return;
+ debug("CarefulUtmp counting slots\n");
+ for (p = windows; p; p = p->w_next)
+ if (p->w_ptyfd >= 0 && p->w_slot != (slot_t)-1)
+ return; /* found one, nothing to do */
+
+ debug("CarefulUtmp: no slots, log one in again.\n");
+ for (p = windows; p; p = p->w_next)
+ if (p->w_ptyfd >= 0) /* no zombies please */
+ break;
+ if (!p)
+ return; /* really hopeless */
+ SetUtmp(p);
+ Msg(0, "Window %d is now logged in.\n", p->w_number);
+}
+#endif /* CAREFULUTMP */
void
InitUtmp()
{
debug1("InitUtmp testing '%s'...\n", UtmpName);
+#ifndef UTMP_HELPER
if ((utmpfd = open(UtmpName, O_RDWR)) == -1)
{
if (errno != EACCES)
@@ -183,10 +262,11 @@ InitUtmp()
utmpok = 0;
return;
}
-#ifdef GETUTENT
+# ifdef GETUTENT
close(utmpfd); /* it was just a test */
utmpfd = -1;
-#endif /* GETUTENT */
+# endif /* GETUTENT */
+#endif /* UTMP_HELPER */
utmpok = 1;
}
@@ -195,34 +275,18 @@ InitUtmp()
int
CountUsers()
{
-# ifdef GETUTENT
- struct utmp *ut, *getutent();
-# else /* GETUTENT */
- struct utmp utmpbuf;
-# endif /* GETUTENT */
+ struct utmp *ut;
int UserCount;
-# ifdef UT_CLOSE
- InitUtmp();
-# endif /* UT_CLOSE */
debug1("CountUsers() - utmpok=%d\n", utmpok);
if (!utmpok)
return 0;
UserCount = 0;
-# ifdef GETUTENT
setutent();
while (ut = getutent())
- if (ut->ut_type == USER_PROCESS)
+ if (SLOT_USED(ut))
UserCount++;
-# else /* GETUTENT */
- (void) lseek(utmpfd, (off_t) 0, 0);
- while (read(utmpfd, &utmpbuf, sizeof(utmpbuf)) == sizeof(utmpbuf))
- if (utmpbuf.ut_name[0] != '\0')
- UserCount++;
-# endif /* GETUTENT */
-# ifdef UT_CLOSE
- close(utmpfd);
-# endif /* UT_CLOSE */
+ UT_CLOSE;
return UserCount;
}
#endif /* USRLIMIT */
@@ -236,97 +300,62 @@ CountUsers()
void
RemoveLoginSlot()
{
-#ifdef GETUTENT
- struct utmp *uu;
-#endif /* GETUTENT */
- struct utmp u; /* 'empty' slot that we write back */
-#ifdef _SEQUENT_
- char *p;
-#endif /* _SEQUENT_ */
+ struct utmp u, *uu;
ASSERT(display);
debug("RemoveLoginSlot: removing your logintty\n");
D_loginslot = TtyNameSlot(D_usertty);
if (D_loginslot == (slot_t)0 || D_loginslot == (slot_t)-1)
return;
-#ifdef UT_CLOSE
- InitUtmp();
-#endif /* UT_CLOSE */
+#ifdef UTMP_HELPER
+ if (eff_uid) /* helpers can't do login slots. sigh. */
+#else
if (!utmpok)
+#endif
{
+ D_loginslot = 0;
debug("RemoveLoginSlot: utmpok == 0\n");
- return;
}
-
+ else
+ {
#ifdef _SEQUENT_
- if (p = ut_find_host(D_loginslot))
- strncpy(D_loginhost, p, sizeof(D_loginhost) - 1);
- D_loginhost[sizeof(D_loginhost) - 1] = 0;
+ {
+ char *p;
+ if ((p = ut_find_host(D_loginslot)) != 0)
+ strncpy(D_loginhost, p, sizeof(D_loginhost) - 1);
+ D_loginhost[sizeof(D_loginhost) - 1] = 0;
+ }
#endif /* _SEQUENT_ */
- bzero((char *) &u, sizeof(u));
-
-#ifdef GETUTENT
- setutent();
- strncpy(u.ut_line, D_loginslot, sizeof(u.ut_line));
- if ((uu = getutline(&u)) == 0)
- {
- Msg(0, "Utmp slot not found -> not removed");
- return;
- }
- D_utmp_logintty = *uu;
-# ifdef _SEQUENT_
- if (ut_delete_user(D_loginslot, uu->ut_pid, 0, 0) == 0)
-# else /* _SEQUENT_ */
- u = *uu;
- /*
- * Ed Hill (ed-hill@uiowa.edu) screen-3.5.2 under AIX 3.2.5
- * when you are down to a single screen, and you log out of it (thus exiting
- * screen), it leaves a stray entry in the utmp file. Seems better:
- * u.ut_type = EMPTY;
- */
- u.ut_type = DEAD_PROCESS;
- u.ut_user[0] = '\0'; /* for Digital UNIX 3.2C, kilbi@rad.rwth-aachen.de */
- u.ut_exit.e_termination = 0;
- u.ut_exit.e_exit= 0;
- if (pututline(&u) == 0)
-# endif /* _SEQUENT_ */
-
-#else /* GETUTENT */
-
- bzero((char *)&D_utmp_logintty, sizeof(u));
- (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(u)), 0);
- if (read(utmpfd, (char *) &D_utmp_logintty, sizeof(u)) != sizeof(u))
- {
- Msg(errno, "cannot read %s ??", UtmpName);
- sleep(1);
- }
-# ifdef UT_UNSORTED
- /* copy tty line */
- bcopy((char *)&D_utmp_logintty, (char *)&u, sizeof(u));
- bzero(u.ut_name, sizeof(u.ut_name));
- bzero(u.ut_host, sizeof(u.ut_host));
-# ifdef linux
- u.ut_type = DEAD_PROCESS;
-# endif
-# endif /* UT_UNSORTED */
- (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(u)), 0);
- if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u))
-
-#endif /* GETUTENT */
-
- {
-#ifdef NETHACK
- if (nethackflag)
- Msg(errno, "%s is too hard to dig in", UtmpName);
+ if ((uu = getutslot(D_loginslot)) == 0)
+ {
+ debug("Utmp slot not found -> not removed");
+ D_loginslot = 0;
+ }
else
-#endif /* NETHACK */
- Msg(errno, "Could not write %s", UtmpName);
+ {
+ D_utmp_logintty = *uu;
+ u = *uu;
+ makedead(&u);
+ if (pututslot(D_loginslot, &u, (char *)0, (struct win *)0) == 0)
+ D_loginslot = 0;
+ }
+ UT_CLOSE;
}
-#ifdef UT_CLOSE
- close(utmpfd);
-#endif /* UT_CLOSE */
debug1(" slot %d zapped\n", (int)D_loginslot);
+ if (D_loginslot == (slot_t)0)
+ {
+ /* couldn't remove slot, do a 'mesg n' at least. */
+ struct stat stb;
+ char *tty;
+ debug("couln't zap slot -> do mesg n\n");
+ D_loginttymode = 0;
+ if ((tty = ttyname(D_userfd)) && stat(tty, &stb) == 0 && stb.st_uid == real_uid && ((int)stb.st_mode & 0777) != 0666)
+ {
+ D_loginttymode = (int)stb.st_mode & 0777;
+ chmod(D_usertty, stb.st_mode & 0600);
+ }
+ }
}
/*
@@ -335,74 +364,27 @@ RemoveLoginSlot()
void
RestoreLoginSlot()
{
+ char *tty;
+
debug("RestoreLoginSlot()\n");
ASSERT(display);
-#ifdef UT_CLOSE
- InitUtmp();
-#endif /* UT_CLOSE */
if (utmpok && D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1)
{
-#ifdef GETUTENT
-# ifdef _SEQUENT_
- int fail;
- debug1(" logging you in again (slot %s)\n", D_loginslot);
-/*
- * We have problems if we add the console and use ut_add_user()
- * because the id will be 'scon' instead of 'co'. So we
- * restore it with pututline(). The reason why we don't use
- * pututline all the time is that we want to set the host field.
- * Unfortunatelly this can only be done with ut_add_user().
- */
- if (*D_loginhost)
- {
- fail = (ut_add_user(D_utmp_logintty.ut_name, D_loginslot, D_utmp_logintty.ut_pid,
- *D_loginhost ? D_loginhost : (char *)0) == 0);
- }
- else
- {
- setutent();
- fail = (pututline(&D_utmp_logintty) == 0);
- }
- if (fail)
-# else /* _SEQUENT_ */
- debug1(" logging you in again (slot %s)\n", D_loginslot);
- setutent();
- if (pututline(&D_utmp_logintty) == 0)
-# endif /* _SEQUENT */
-#else /* GETUTENT */
- debug1(" logging you in again (slot %d)\n", D_loginslot);
-# ifdef sequent
- /*
- * call sequent undocumented routine to count logins
- * and add utmp entry if possible
- */
- if (add_utmp(D_loginslot, &D_utmp_logintty) == -1)
-# else /* sequent */
- (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(struct utmp)), 0);
- if (write(utmpfd, (char *) &D_utmp_logintty, sizeof(struct utmp))
- != sizeof(struct utmp))
-# endif /* sequent */
-#endif /* GETUTENT */
- {
-#ifdef NETHACK
- if (nethackflag)
- Msg(errno, "%s is too hard to dig in", UtmpName);
- else
-#endif /* NETHACK */
- Msg(errno,"Could not write %s", UtmpName);
- }
+ debug1(" logging you in again (slot %#x)\n", (int)D_loginslot);
+ if (pututslot(D_loginslot, &D_utmp_logintty, D_loginhost, (struct win *)0) == 0)
+ Msg(errno,"Could not write %s", UtmpName);
}
-#ifdef UT_CLOSE
- close(utmpfd);
-#endif /* UT_CLOSE */
- D_loginslot = (slot_t) 0;
+ UT_CLOSE;
+ D_loginslot = (slot_t)0;
+ if (D_loginttymode && (tty = ttyname(D_userfd)))
+ chmod(tty, D_loginttymode);
}
/*
* Construct a utmp entry for window wi.
- * the hostname field reflects what we know about the user (i.e. display)
+ * the hostname field reflects what we know about the user (display)
* location. If d_loginhost is not set, then he is local and we write
* down the name of his terminal line; else he is remote and we keep
* the hostname here. The letter S and the window id will be appended.
@@ -415,21 +397,16 @@ struct win *wi;
{
register char *p;
register slot_t slot;
-#ifndef _SEQUENT_
- char *line;
-#endif
struct utmp u;
int saved_ut;
#ifdef UTHOST
-# ifdef _SEQUENT_
- char host[100+5];
-# else /* _SEQUENT_ */
- char host[sizeof(D_utmp_logintty.ut_host)+5];
-# endif /* _SEQUENT_ */
+ char host[sizeof(D_loginhost) + 15];
+#else
+ int host = 0;
#endif /* UTHOST */
wi->w_slot = (slot_t)0;
- if (!utmpok)
+ if (!utmpok || wi->w_type != W_TYPE_PTY)
return -1;
if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t)0)
{
@@ -437,24 +414,20 @@ struct win *wi;
return -1;
}
debug2("SetUtmp %d will get slot %d...\n", wi->w_number, (int)slot);
-#ifdef UT_CLOSE
- InitUtmp();
-#endif /* UT_CLOSE */
- bzero((char *) &u, sizeof(u));
- if ((saved_ut = bcmp((char *) &wi->w_savut, (char *) &u, sizeof(u))))
+ bzero((char *)&u, sizeof(u));
+ if ((saved_ut = bcmp((char *) &wi->w_savut, (char *)&u, sizeof(u))))
/* restore original, of which we will adopt all fields but ut_host */
- bcopy((char *) &wi->w_savut, (char *) &u, sizeof(u));
+ bcopy((char *)&wi->w_savut, (char *) &u, sizeof(u));
+
+ if (!saved_ut)
+ makeuser(&u, stripdev(wi->w_tty), LoginName, wi->w_pid);
#ifdef UTHOST
- host[sizeof(host)-5] = '\0';
+ host[sizeof(host) - 15] = '\0';
if (display)
{
-# ifdef _SEQUENT_
- strncpy(host, D_loginhost, sizeof(host) - 5);
-# else /* _SEQUENT */
- strncpy(host, D_utmp_logintty.ut_host, sizeof(host) - 5);
-# endif /* _SEQUENT */
+ strncpy(host, D_loginhost, sizeof(host) - 15);
if (D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1 && host[0] != '\0')
{
/*
@@ -463,6 +436,7 @@ struct win *wi;
* "faui45:s.0" or
* "132.199.81.4:s.0" (even this may hurt..), but not
* "faui45.informati"......:s.0
+ * HPUX uses host:0.0, so chop at "." and ":" (Eric Backus)
*/
for (p = host; *p; p++)
if ((*p < '0' || *p > '9') && (*p != '.'))
@@ -470,7 +444,7 @@ struct win *wi;
if (*p)
{
for (p = host; *p; p++)
- if (*p == '.')
+ if (*p == '.' || (*p == ':' && p != host))
{
*p = '\0';
break;
@@ -479,90 +453,34 @@ struct win *wi;
}
else
{
- strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 6);
+ strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 15 - 1);
host[0] = ':';
}
}
else
- strncpy(host, "local", sizeof(host) - 5);
- sprintf(host + strlen(host), ":S.%c", '0' + wi->w_number);
+ strncpy(host, "local", sizeof(host) - 15);
+
+ sprintf(host + strlen(host), ":S.%d", wi->w_number);
debug1("rlogin hostname: '%s'\n", host);
+
# if !defined(_SEQUENT_) && !defined(sequent)
strncpy(u.ut_host, host, sizeof(u.ut_host));
# endif
#endif /* UTHOST */
-#ifdef _SEQUENT_
- if (ut_add_user(saved_ut ? u.ut_user : LoginName, slot, saved_ut ? u.ut_pid : wi->w_pid, host) == 0)
-#else /* _SEQUENT_ */
- if (!saved_ut)
- { /* make new utmp from scratch */
- line = stripdev(wi->w_tty);
-# ifdef GETUTENT
- strncpy(u.ut_user, LoginName, sizeof(u.ut_user));
- /* Now the tricky part... guess ut_id */
-# ifdef sgi
- strncpy(u.ut_id, line + 3, sizeof(u.ut_id));
-# else /* sgi */
-# ifdef _IBMR2
- strncpy(u.ut_id, line, sizeof(u.ut_id));
-# else
- strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id));
-# endif
-# endif /* sgi */
- strncpy(u.ut_line, line, sizeof(u.ut_line));
- u.ut_pid = wi->w_pid;
- u.ut_type = USER_PROCESS;
- (void) time((time_t *)&u.ut_time);
- } /* !saved_ut {-: */
- setutent();
- if (pututline(&u) == 0)
-# else /* GETUTENT */
- strncpy(u.ut_line, line, sizeof(u.ut_line));
- strncpy(u.ut_name, LoginName, sizeof(u.ut_name));
-# if defined(linux) /* should have GETUTENT */
- u.ut_type = USER_PROCESS;
- u.ut_pid = wi->w_pid;
- strncpy(u.ut_id, line + 3, sizeof(u.ut_id));
-# endif /* linux */
- (void) time((time_t *)&u.ut_time); /* cast needed for ultrix */
- } /* !saved_ut */
-# ifdef sequent
- /*
- * call sequent undocumented routine to count logins and
- * add utmp entry if possible
- */
- if (add_utmp(slot, &u) == -1)
-# else /* sequent */
- (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
- if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u))
-# endif /* sequent */
-# endif /* GETUTENT */
-#endif /* _SEQUENT_ */
-
+ if (pututslot(slot, &u, host, wi) == 0)
{
-#ifdef NETHACK
- if (nethackflag)
- Msg(errno, "%s is too hard to dig in", UtmpName);
- else
-#endif /* NETHACK */
Msg(errno,"Could not write %s", UtmpName);
-#ifdef UT_CLOSE
- close(utmpfd);
-#endif /* UT_CLOSE */
+ UT_CLOSE;
return -1;
}
debug("SetUtmp successful\n");
wi->w_slot = slot;
-#ifdef UT_CLOSE
- close(utmpfd);
-#endif /* UT_CLOSE */
- bcopy((char *) &u, (char *) &wi->w_savut, sizeof(u));
+ bcopy((char *)&u, (char *)&wi->w_savut, sizeof(u));
+ UT_CLOSE;
return 0;
}
-
-
/*
* if slot could be removed or was 0, wi->w_slot = -1;
* else not changed.
@@ -572,152 +490,281 @@ int
RemoveUtmp(wi)
struct win *wi;
{
-#ifdef GETUTENT
- struct utmp *uu;
-#endif /* GETUTENT */
- struct utmp u;
+ struct utmp u, *uu;
slot_t slot;
slot = wi->w_slot;
-#ifdef GETUTENT
- debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ?
- "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot));
-#else /* GETUTENT */
- debug1("RemoveUtmp(wi.slot: %d)\n", slot);
-#endif /* GETUTENT */
-#ifdef UT_CLOSE
- InitUtmp();
-#endif /* UT_CLOSE */
+ debug1("RemoveUtmp slot=%#x\n", slot);
if (!utmpok)
return -1;
- if (slot == (slot_t) 0 || slot == (slot_t) -1)
+ if (slot == (slot_t)0 || slot == (slot_t)-1)
{
- debug1("There is no utmp-slot to be removed(%d)\n", (int)slot);
- wi->w_slot = (slot_t) -1;
+ wi->w_slot = (slot_t)-1;
return 0;
}
bzero((char *) &u, sizeof(u));
-#ifdef GETUTENT
- setutent();
-# ifdef sgi
- bcopy((char *) &wi->w_savut, (char *) &u, sizeof(u));
+#ifdef sgi
+ bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u));
uu = &u;
-# else
- strncpy(u.ut_line, slot, sizeof(u.ut_line));
- if ((uu = getutline(&u)) == 0)
+#else
+ if ((uu = getutslot(slot)) == 0)
{
Msg(0, "Utmp slot not found -> not removed");
return -1;
}
bcopy((char *)uu, (char *)&wi->w_savut, sizeof(wi->w_savut));
-# endif
-# ifdef _SEQUENT_
- if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
-# else /* _SEQUENT_ */
+#endif
u = *uu;
- u.ut_type = DEAD_PROCESS;
- u.ut_exit.e_termination = 0;
- u.ut_exit.e_exit= 0;
- if (pututline(&u) == 0)
-# endif /* _SEQUENT_ */
-#else /* GETUTENT */
- (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
- if (read(utmpfd, (char *) &wi->w_savut, sizeof(u)) != sizeof(u))
+ makedead(&u);
+ if (pututslot(slot, &u, (char *)0, wi) == 0)
{
- bzero((char *)&wi->w_savut, sizeof(wi->w_savut));
- Msg(errno, "cannot read %s?", UtmpName);
- sleep(1);
- }
-# ifdef UT_UNSORTED
- bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u));
- bzero(u.ut_name, sizeof(u.ut_name));
- bzero(u.ut_host, sizeof(u.ut_host));
-# ifdef linux
- u.ut_type = DEAD_PROCESS;
-# endif
-# endif /* UT_UNSORTED */
- (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
- if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u))
-#endif /* GETUTENT */
- {
-#ifdef NETHACK
- if (nethackflag)
- Msg(errno, "%s is too hard to dig in", UtmpName);
- else
-#endif /* NETHACK */
Msg(errno,"Could not write %s", UtmpName);
-#ifdef UT_CLOSE
- close(utmpfd);
-#endif /* UT_CLOSE */
+ UT_CLOSE;
return -1;
}
debug("RemoveUtmp successfull\n");
- wi->w_slot = (slot_t) -1;
-#ifdef UT_CLOSE
- close(utmpfd);
-#endif /* UT_CLOSE */
+ wi->w_slot = (slot_t)-1;
+ UT_CLOSE;
return 0;
}
-/*
- * TtyNameSlot:
- * return an index, where the named tty is found in utmp.
+/*********************************************************************
+ *
+ * routines using the getut* api
*/
-static slot_t
+#ifdef GETUTENT
+
+#define SLOT_USED(u) (u->ut_type == USER_PROCESS)
+
+static struct utmp *
+getutslot(slot)
+slot_t slot;
+{
+ struct utmp u;
+ bzero((char *)&u, sizeof(u));
+ strncpy(u.ut_line, slot, sizeof(u.ut_line));
+ setutent();
+ return getutline(&u);
+}
+
+static int
+pututslot(slot, u, host, wi)
+slot_t slot;
+struct utmp *u;
+char *host;
+struct win *wi;
+{
+#ifdef _SEQUENT_
+ if (SLOT_USED(u) && host && *host)
+ return ut_add_user(u.ut_name, slot, u.ut_pid, host) != 0;
+ if (!SLOT_USED(u))
+ return ut_delete_user(slot, u.ut_pid, 0, 0) != 0;
+#endif
+#ifdef HAVE_UTEMPTER
+ if (eff_uid && wi->w_ptyfd != -1)
+ {
+ /* sigh, linux hackers made the helper functions void */
+ if (SLOT_USED(u))
+ addToUtmp(wi->w_tty, host, wi->w_ptyfd);
+ else
+ removeLineFromUtmp(wi->w_tty, wi->w_ptyfd);
+ return 1; /* pray for success */
+ }
+#endif
+ setutent();
+ return pututline(u) != 0;
+}
+
+static void
+makedead(u)
+struct utmp *u;
+{
+ u->ut_type = DEAD_PROCESS;
+#if !defined(linux) || defined(EMPTY)
+ u->ut_exit.e_termination = 0;
+ u->ut_exit.e_exit = 0;
+#endif
+#if !defined(sun) || !defined(SVR4)
+ u->ut_user[0] = 0; /* for Digital UNIX, kilbi@rad.rwth-aachen.de */
+#endif
+}
+
+static void
+makeuser(u, line, user, pid)
+struct utmp *u;
+char *line, *user;
+int pid;
+{
+ u->ut_type = USER_PROCESS;
+ strncpy(u->ut_user, user, sizeof(u->ut_user));
+ /* Now the tricky part... guess ut_id */
+#if defined(sgi) || defined(linux)
+ strncpy(u->ut_id, line + 3, sizeof(u->ut_id));
+#else /* sgi */
+# ifdef _IBMR2
+ strncpy(u->ut_id, line, sizeof(u->ut_id));
+# else
+ strncpy(u->ut_id, line + strlen(line) - 2, sizeof(u->ut_id));
+# endif
+#endif /* sgi */
+ strncpy(u->ut_line, line, sizeof(u->ut_line));
+ u->ut_pid = pid;
+ (void)time((time_t *)&u->ut_time);
+}
+
+static slot_t
TtyNameSlot(nam)
char *nam;
{
- char *name;
- register slot_t slot;
+ return stripdev(nam);
+}
+
+
+#else /* GETUTENT */
+
+/*********************************************************************
+ *
+ * getut emulation for systems lacking the api
+ */
+
+static struct utmp uent;
+
+#define SLOT_USED(u) (u.ut_name[0] != 0)
+
+static int
+initutmp()
+{
+ if (utmpfd >= 0)
+ return 1;
+ return (utmpfd = open(UtmpName, O_RDWR)) >= 0;
+}
+
+static void
+setutent()
+{
+ if (utmpfd >= 0)
+ (void)lseek(utmpfd, (off_t)0, 0);
+}
+
+static void
+endutent()
+{
+ if (utmpfd >= 0)
+ close(utmpfd);
+ utmpfd = -1;
+}
+
+static struct utmp *
+getutent()
+{
+ if (utmpfd < 0 && !initutmp())
+ return 0;
+ if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent))
+ return 0;
+ return &uent;
+}
+
+static struct utmp *
+getutslot(slot)
+slot_t slot;
+{
+ if (utmpfd < 0 && !initutmp())
+ return 0;
+ lseek(utmpfd, (off_t)(slot * sizeof(struct utmp)), 0);
+ if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent))
+ return 0;
+ return &uent;
+}
+
+static int
+pututslot(slot, u, host, wi)
+slot_t slot;
+struct utmp *u;
+char *host;
+struct win *wi;
+{
+#ifdef sequent
+ if (SLOT_USED(u))
+ return add_utmp(slot, u) != -1;
+#endif
+ if (utmpfd < 0 && !initutmp())
+ return 0;
+ lseek(utmpfd, (off_t)(slot * sizeof(*u)), 0);
+ if (write(utmpfd, u, sizeof(*u)) != sizeof(*u))
+ return 0;
+ return 1;
+}
+
+
+static void
+makedead(u)
+struct utmp *u;
+{
#ifdef UT_UNSORTED
- struct utmp u;
+ bzero(u->ut_name, sizeof(u->ut_name));
+# ifdef UTHOST
+ bzero(u->ut_host, sizeof(u->ut_host));
+# endif
#else
-# ifndef GETUTENT
- register struct ttyent *tp;
-# endif /* GETUTENT */
-#endif /* UT_UNSORTED */
+ bzero((char *)u, sizeof(*u));
+#endif
+}
- debug1("TtyNameSlot(%s)\n", nam);
-#ifdef UT_CLOSE
- InitUtmp();
-#endif /* UT_CLOSE */
- if (!utmpok || nam == 0)
- return (slot_t)0;
- name = stripdev(nam);
-#ifdef GETUTENT
- slot = name;
-#else /* GETUTENT */
-# ifdef UT_UNSORTED
- slot = 0;
- (void) lseek(utmpfd, (off_t) 0, 0);
- while ((read(utmpfd, (char *)&u, sizeof(u)) == sizeof(u))
- && (strcmp(u.ut_line, name)))
- slot++;
-# else /* UT_UNSORTED*/
+
+static void
+makeuser(u, line, user, pid)
+struct utmp *u;
+char *line, *user;
+int pid;
+{
+ strncpy(u->ut_line, line, sizeof(u->ut_line));
+ strncpy(u->ut_name, user, sizeof(u->ut_name));
+ (void)time((time_t *)&u->ut_time);
+}
+
+static slot_t
+TtyNameSlot(nam)
+char *nam;
+{
+ slot_t slot;
+ char *line;
+#ifndef UT_UNSORTED
+ struct ttyent *tp;
+#endif
+
+ line = stripdev(nam);
+#ifdef UT_UNSORTED
+ setutent();
+ if (utmpfd < 0)
+ return -1;
+ for (slot = 0; getutent(); slot++)
+ if (strcmp(uent.ut_line, line) == 0)
+ break;
+ UT_CLOSE;
+#else
slot = 1;
setttyent();
- while ((tp = getttyent()) != 0 && strcmp(name, tp->ty_name) != 0)
+ while ((tp = getttyent()) != 0 && strcmp(line, tp->ty_name) != 0)
slot++;
-# endif /* UTNOKEEP */
-#endif /* GETUTENT */
-
-#ifdef UT_CLOSE
- close(utmpfd);
#endif
return slot;
}
+#endif /* GETUTENT */
-#if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED)
-/*
+/*********************************************************************
+ *
* Cheap plastic imitation of ttyent routines.
*/
+#if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED)
+
+
static char *tt, *ttnext;
static char ttys[] = "/etc/ttys";
@@ -805,3 +852,21 @@ getlogin()
}
# endif /* BUGGYGETLOGIN */
+#if defined(linux) && defined(GETUTENT)
+# undef pututline
+
+/* aargh, linux' pututline returns void! */
+struct utmp *
+xpututline(u)
+struct utmp *u;
+{
+ struct utmp *u2;
+ pututline(u);
+ setutent();
+ u2 = getutline(u);
+ if (u2 == 0)
+ return u->ut_type == DEAD_PROCESS ? u : 0;
+ return u->ut_type == u2->ut_type ? u : 0;
+}
+#endif
+