summaryrefslogtreecommitdiffstats
path: root/src/appl/libpty/update_utmp.c
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2009-11-22 14:58:54 +0000
committerGreg Hudson <ghudson@mit.edu>2009-11-22 14:58:54 +0000
commit14590b7c281e1fbf68afec2f3f4104b87e6010f4 (patch)
treee3f6c44278d9a69c45fbabd4b93146a99aa29244 /src/appl/libpty/update_utmp.c
parent829462f1ae36623021b57a03aa1e4e6bb2dfbb6d (diff)
downloadkrb5-14590b7c281e1fbf68afec2f3f4104b87e6010f4.tar.gz
krb5-14590b7c281e1fbf68afec2f3f4104b87e6010f4.tar.xz
krb5-14590b7c281e1fbf68afec2f3f4104b87e6010f4.zip
Unbundle applications into separate repository
Remove libpty, gssftp, telnet, and the bsd applications from the source tree, build system, and tests. Docs still need to be updated to remove mentions of the applications. The build system should be simplified now that we're down to one configure script and don't need some of the functionality currently in aclocal.m4. ticket: 6583 status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23305 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/appl/libpty/update_utmp.c')
-rw-r--r--src/appl/libpty/update_utmp.c724
1 files changed, 0 insertions, 724 deletions
diff --git a/src/appl/libpty/update_utmp.c b/src/appl/libpty/update_utmp.c
deleted file mode 100644
index bec57fa318..0000000000
--- a/src/appl/libpty/update_utmp.c
+++ /dev/null
@@ -1,724 +0,0 @@
-/*
- * pty_update_utmp: Update or create a utmp entry
- *
- * Copyright 1995, 2001 by the Massachusetts Institute of Technology.
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that copyright notice and this permission
- * notice appear in supporting documentation, and that the name of
- * M.I.T. not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability
- * of this software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
-/*
- * Rant about the historical vagaries of utmp:
- * -------------------------------------------
- *
- * There exist many subtly incompatible incarnations of utmp, ranging
- * from BSD to System V to Unix98 and everywhere in between. This
- * rant attempts to collect in one place as much knowledge as possible
- * about this portability nightmare.
- *
- * BSD:
- * ----
- *
- * The simplest (and earliest? possibly dating back to Version 7...)
- * case is 4.x BSD utmp/wtmp. There are no auxiliary files. There is
- * only a struct utmp, declared in utmp.h. Its contents usually
- * include:
- *
- * char ut_line[]
- * char ut_name[]
- * char ut_host[]
- * long ut_time
- *
- * The meanings of these fields follow their names reasonbly well.
- * The ut_line field usually is the pathname of the tty device
- * associated with the login, with the leading "/dev/" stripped off.
- *
- * It is believed that ut_host is nul-terminated, while the other
- * strings are merely nul-padded.
- *
- * Generally, ut_name is an empty string for a logout record in both
- * utmp and wtmp. For entries made by the window system or other
- * terminal emulation stuff, ut_host is an empty string (at least
- * under SunOS 4.x, it seems). The macro nonuser() is used to
- * determine this if a utmp entry is made by the window system on at
- * least SunOS 4.x.
- *
- * The native login never clears its own utmp entry or writes its own
- * logout record; its parent (one of init, rlogind, telnetd, etc.)
- * should handle that. In theory, getty could do that, but getty
- * usually doesn't fork to exec login.
- *
- * Old (c. 1984) System V:
- * -----------------------
- *
- * This is partially conjecture, based on some reading of
- * /usr/xpg2include/utmp.h on a SunOS 4.x system. There appears to
- * only be a struct utmp, declared in utmp.h. It is likely used for
- * both utmp and wtmp files. It is quite likely that the utmp is only
- * supposed to be accessed via the getutline()/pututline() API. The
- * contents of struct utmp seem to include:
- *
- * char ut_user[]
- * char ut_id[]
- * char ut_line[]
- * short ut_pid
- * short ut_type
- * struct exit_status ut_exit
- * time_t ut_time
- *
- * On these systems, ut_name is often #define'ed to be ut_user to be
- * somewhat compatible with the BSD-style utmp. Note that there is
- * not necessarily a ut_host field in this utmp structure.
- *
- * The ut_id field bears some explanation. The systems that use this
- * style of utmp also use a sysV-ish init, which starts processes out
- * of /etc/inittab rather than /etc/ttys, and has the concept of
- * runlevels. The first field in each line of /etc/inittab contains a
- * unique ID field. init probably gets really confused if there are
- * conflicts here. Every process that init starts gets its own entry
- * written to utmp.
- *
- * It is possible for multiple entries to have the same ut_line but
- * different ut_id values, since the sysadmin will be responsible for
- * assigning values to ut_id. Usually, ut_id is four characters,
- * while the permissible unique ID values for entries in /etc/inittab
- * are constrained to two characters, but this is not always the
- * case. In the case where we are emulating the vendor's login
- * program and being run out of getty, we need to account for which
- * value of ut_id was used by the getty, since pututline() will search
- * based on ut_id and not ut_line for some reason.
- *
- * The ut_pid and ut_type fields are used for bookkeeping by init.
- * The ut_type field gets the value INIT_PROCESS for processes started
- * by init. It gets the value LOGIN_PROCESS if it is a process that
- * is prompting for a login name, and it gets the value USER_PROCESS
- * for an actual valid login. When the process dies, either init
- * cleans up after it and records a DEAD_PROCESS entry in utmp, or the
- * process itself does so. It's not completely clear which actually
- * happens, though it is quite possible that init only cleans up after
- * processes that it starts itself.
- *
- * Other values of ut_type exist; they're largely internal bookkeeping
- * for init's runlevels and such, and don't really interest this
- * library at all.
- *
- * The ut_exit field contains the following members:
- *
- * short e_termination
- * short e_exit
- *
- * It is not clear how these values are used; presumably they record
- * the process termination status of dead processes.
- *
- * There is no uniform API for manipulating wtmp on systems that use
- * this sort of utmp structure; it can be assumed that the structure
- * can be directly written to the wtmp file.
- *
- * Unix98:
- * -------
- *
- * This description also likely applies to later System V derivatives
- * as well as systems conforming to earlier X/Open standards such as
- * XPG4. There is a new header, utmpx.h, which defines a struct utmpx
- * and a new getutxline()/pututxline() API for accessing it. Some
- * systems actually have a utmpx file on disk; others use the utmpx
- * API to access a file named utmp, just to further confuse matters.
- *
- * The utmpx structure is guaranteed (by Unix98) to contain at least
- * the following:
- *
- * char ut_user[]
- * char ut_line[]
- * char ut_id[]
- * pid_t ut_pid
- * short ut_type
- * struct timeval ut_tv
- *
- * It is not guaranteed to contain, but often does contain, the
- * following:
- *
- * char ut_host[]
- * int ut_syslen
- * int ut_session
- * struct exit_status ut_exit
- *
- * The ut_syslen field, on systems that contain it, contains the
- * number of significant characters in ut_host, including the
- * terminating nul character.
- *
- * The main difference between this struct utmpx and the struct utmp
- * used by early sysV derivatives is the change from a time_t or long
- * for ut_time to a struct timeval for ut_tv.
- *
- * Comments in various header files imply that ut_session is used for
- * window systems, but it's not clear how. Perhaps it contains the
- * session ID of the session running the window system, e.g. the xdm
- * or X server on an X11 system.
- *
- * Most of the description of the earlier sysV format probably applies
- * here, with suitable changes of names. On systems that maintain
- * utmpx and utmp files in parallel, it is assumed that using the
- * pututxline() API is sufficient to keep them in sync. There are no
- * known counterexamples to this.
- *
- * Nevertheless, there are, on some systems, API functions getutmp()
- * and getutmpx() that appear to convert from struct utmpx to struct
- * utmp and vice versa. This could be useful when there is a wtmp
- * file but not a corresponding wtmpx file.
- *
- * Incidentally, ut_exit is sometimes present in the struct utmp but
- * not the struct utmpx for a given system. Sometimes, it exists in
- * both, but contains differently named members. It's probably one of
- * the least portable pieces in this whole mess.
- *
- * Known Quirks of Specific OSes:
- * ------------------------------
- *
- * Solaris 2.x:
- *
- * Has utmpd, which will automatically clean up utmpx, utmp, wtmpx,
- * wtmp after process termination, provided that pututxline() was
- * used.
- *
- * Solaris 8 seems to have a bug in utmpname() that causes
- * garbage filenames to be generated. Solaris 7 (and possibly Solaris
- * 8) have a bug in utmpxname() that prevents them from looking at
- * anything other than /var/adm/utmpx, it seems. For some reason,
- * though, utmpname() goes and looks at the corresponding utmpx file.
- *
- * Solaris 7 (and may be 8 as well) has a bug in pututline() that
- * interacts badly with prior invocation of getutline(): if
- * getutline() finds an entry, calling pututline() without first
- * calling setutent() will overwrite the record following the one that
- * was intended.
- *
- * Also, ut_exit in utmpx contains ut_e_termination and
- * ut_e_exit (otherwise it contains the expected e_termination and
- * e_exit) only if _XPG4_2 is defined and __EXTENSIONS__ is not, which
- * is not a compilation environment we're likely to encourage. The
- * ut_exit field of utmp contains the expected fields.
- *
- * If _XPG4_2 is not defined or __EXTENSIONS__ is defined, the
- * functions getutmp(), getutmpx(), updwtmp(), and updwtmpx() are
- * available, as well as the undocumented functions makeutx() and
- * modutx().
- *
- * All the files utmp, utmpx, wtmp, and wtmpx exist.
- *
- * HP-UX 10.x:
- *
- * There is a curious interaction between how we allocate pty masters
- * and how ttyname() works. It seems that if /dev/ptmx/clone is
- * opened, a call to ptsname() on the master fd gets a filename of the
- * form /dev/pty/tty[pqrs][0-9a-f], while ttyname() called on a fd
- * opened with that filename returns a filename of the form
- * /dev/tty[pqrs][0-9a-f] instead. These two filenames are actually
- * hardlinks to the same special device node, so it shouldn't be a
- * security problem.
- *
- * We can't call ttyname() in the parent because it would involve
- * possibly acquiring a controlling terminal (which would be
- * potentially problematic), so we have to resort to some trickery in
- * order to ensure that the ut_line in the wtmp logout and login
- * records match. If they don't match, various utilities such as last
- * will get confused. Of course it's likely an OS bug that ttyname()
- * and ptsname() are inconsistent in this way, but it's one that isn't
- * too painful to work around.
- *
- * It seems that the HP-UX native telnetd has problems similar to ours
- * in this area, though it manages to write the correct logout record
- * to wtmp somehow. It probably does basically what we do here:
- * search for a record with a matching ut_pid and grab its ut_line for
- * writing into the logout record. Interestingly enough, its
- * LOGIN_PROCESS record is of the form pty/tty[pqrs][0-9][a-f].
- *
- * Uses four-character unique IDs for /etc/inittab, which means that
- * programs not running out of init should use two-character ut_id
- * fields to avoid conflict.
- *
- * In utmpx, ut_exit contains __e_termination and __e_exit, while
- * ut_exit in utmp contains the expected fields.
- *
- * There is no wtmpx file, despite there being utmp and utmpx files.
- *
- * HP-UX 11.23:
- *
- * In addition to other HP-UX issues, 11.23 includes yet another utmp
- * management interface in utmps.h. This interface updates a umtpd
- * daemon which then manages local files. Directly accessing the files
- * through the existing, yet deprecated, utmp.h interface results in
- * nothing.
- *
- * Irix 6.x:
- *
- * In utmpx, ut_exit contains __e_termination and __e_exit, which get
- * #define aliases e_termination and e_exit if _NO_XOPEN4 is true.
- * Curiously enough, utmp.h declares ut_exit to have __e_termination
- * and __e_exit as well, but does #define e_termination
- * __e_termination, etc. if another header (utmpx.h) hasn't already
- * declared struct __exit_status. It seems that the default
- * compilation environment has the effect of making _NO_XOPEN4 true
- * though.
- *
- * If _NO_XOPEN4 is true, getutmp(), getutmpx(), updwtmp(), and
- * updwtmpx() are available, as well as the undocumented functions
- * makeutx() and modutx().
- *
- * All the files utmp, utmpx, wtmp, and wtmpx exist.
- *
- * Tru64 Unix 4.x:
- *
- * In utmpx, ut_exit contains ut_termination and ut_exit, while utmp
- * contains the expected fields. The files utmp and wtmp seem to
- * exist, but not utmpx or wtmpx.
- *
- * When writing a logout entry, the presence of a non-empty username
- * confuses last.
- *
- * AIX 4.3.x:
- *
- * The ut_exit field seems to exist in utmp, but not utmpx. The files
- * utmp and wtmp seem to exist, but not utmpx, or wtmpx.
- *
- * libpty Implementation Decisions:
- * --------------------------------
- *
- * We choose to use the pututxline() whenever possible, falling back
- * to pututline() and calling write() to write out struct utmp if
- * necessary. The code to handle pututxline() and pututline() is
- * rather similar, since the structure members are quite similar, and
- * we make the assumption that it will never be necessary to call
- * both. This allows us to avoid duplicating lots of code, by means
- * of some slightly demented macros.
- *
- * If neither pututxline() nor pututline() are available, we assume
- * BSD-style utmp files and behave accordingly, writing the structure
- * out to disk ourselves.
- *
- * On systems where updwtmpx() or updwtmp() are available, we use
- * those to update the wtmpx or wtmp file. When they're not
- * available, we write the utmpx or utmp structure out to disk
- * ourselves, though sometimes conversion from utmpx to utmp format is
- * needed.
- *
- * We assume that at logout the system is ok with with having an empty
- * username both in utmp and wtmp.
- */
-
-#include "com_err.h"
-#include "libpty.h"
-#include "pty-int.h"
-#include "k5-platform.h"
-
-#if !defined(UTMP_FILE) && defined(_PATH_UTMP)
-#define UTMP_FILE _PATH_UTMP
-#endif
-
-/* if it is *still* missing, assume SunOS */
-#ifndef UTMP_FILE
-#define UTMP_FILE "/etc/utmp"
-#endif
-
-/*
- * The following grossness exists to avoid duplicating lots of code
- * between the cases where we have an old-style sysV utmp and where we
- * have a modern (Unix98 or XPG4) utmpx, or the new (hp-ux 11.23) utmps.
- * See the above history rant for further explanation.
- */
-#if defined(HAVE_SETUTXENT) || defined(HAVE_SETUTENT) || defined(HAVE_SETUTSENT)
-#ifdef HAVE_SETUTSENT
-#include <utmps.h>
-#define PTY_STRUCT_UTMPX struct utmps
-#define PTY_SETUTXENT setutsent
-#define PTY_GETUTXENT GETUTSENT
-#define PTY_GETUTXLINE GETUTSLINE
-#define PTY_PUTUTXLINE PUTUTSLINE
-#define PTY_ENDUTXENT endutsent
-#else
-#ifdef HAVE_SETUTXENT
-#define PTY_STRUCT_UTMPX struct utmpx
-#define PTY_SETUTXENT setutxent
-#define PTY_GETUTXENT getutxent
-#define PTY_GETUTXLINE getutxline
-#define PTY_PUTUTXLINE pututxline
-#define PTY_ENDUTXENT endutxent
-#else
-#define PTY_STRUCT_UTMPX struct utmp
-#define PTY_SETUTXENT setutent
-#define PTY_GETUTXENT getutent
-#define PTY_GETUTXLINE getutline
-#define PTY_PUTUTXLINE pututline
-#define PTY_ENDUTXENT endutent
-#endif
-#endif
-static int better(const PTY_STRUCT_UTMPX *, const PTY_STRUCT_UTMPX *,
- const PTY_STRUCT_UTMPX *);
-static int match_pid(const PTY_STRUCT_UTMPX *,
- const PTY_STRUCT_UTMPX *);
-static PTY_STRUCT_UTMPX *best_utxent(const PTY_STRUCT_UTMPX *);
-
-/*
- * Utility function to determine whether A is a better match for
- * SEARCH than B. Should only be called by best_utxent().
- */
-static int
-better(const PTY_STRUCT_UTMPX *search,
- const PTY_STRUCT_UTMPX *a, const PTY_STRUCT_UTMPX *b)
-{
- if (strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) {
- if (!strncmp(search->ut_id, a->ut_id, sizeof(a->ut_id))) {
- return 1;
- }
- }
-
- if (strncmp(a->ut_id, b->ut_id, sizeof(b->ut_id))) {
- /* Got different UT_IDs; find the right one. */
- if (!strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) {
- /* Old entry already matches; use it. */
- return 0;
- }
- if (a->ut_type == LOGIN_PROCESS
- && b->ut_type != LOGIN_PROCESS) {
- /* Prefer LOGIN_PROCESS */
- return 1;
- }
- if (search->ut_type == DEAD_PROCESS
- && a->ut_type == USER_PROCESS
- && b->ut_type != USER_PROCESS) {
- /*
- * Try USER_PROCESS if we're entering a DEAD_PROCESS.
- */
- return 1;
- }
- return 0;
- } else {
- /*
- * Bad juju. We shouldn't get two entries with identical
- * ut_id fields for the same value of ut_line. pututxline()
- * will probably pick the first entry, in spite of the strange
- * state of utmpx, if we rewind with setutxent() first.
- *
- * For now, return 0, to force the earlier entry to be used.
- */
- return 0;
- }
-}
-
-static int
-match_pid(const PTY_STRUCT_UTMPX *search, const PTY_STRUCT_UTMPX *u)
-{
- if (u->ut_type != LOGIN_PROCESS && u->ut_type != USER_PROCESS)
- return 0;
- if (u->ut_pid == search->ut_pid) {
- /*
- * One of ut_line or ut_id should match, else some nastiness
- * may result. We can fall back to searching by ut_line if
- * need be. This should only really break if we're login.krb5
- * running out of getty, or we're cleaning up after the vendor
- * login, and either the vendor login or the getty has
- * different ideas than we do of what both ut_id and ut_line
- * should be. It should be rare, though. We may want to
- * remove this restriction later.
- */
- if (!strncmp(u->ut_line, search->ut_line, sizeof(u->ut_line)))
- return 1;
- if (!strncmp(u->ut_id, search->ut_id, sizeof(u->ut_id)))
- return 1;
- }
- return 0;
-}
-
-/*
- * This expects to be called with SEARCH pointing to a struct utmpx
- * with its ut_type equal to USER_PROCESS or DEAD_PROCESS, since if
- * we're making a LOGIN_PROCESS entry, we presumably don't care about
- * preserving existing state. At the very least, the ut_pid, ut_line,
- * ut_id, and ut_type fields must be filled in by the caller.
- */
-static PTY_STRUCT_UTMPX *
-best_utxent(const PTY_STRUCT_UTMPX *search)
-{
- PTY_STRUCT_UTMPX utxtmp, *utxp;
- int i, best;
-
- memset(&utxtmp, 0, sizeof(utxtmp));
-
- /*
- * First, search based on pid, but only if non-zero.
- */
- if (search->ut_pid) {
- i = 0;
- PTY_SETUTXENT();
- while ((utxp = PTY_GETUTXENT()) != NULL) {
- if (match_pid(search, utxp)) {
- return utxp;
- }
- i++;
- }
- }
- /*
- * Uh-oh, someone didn't enter our pid. Try valiantly to search
- * by terminal line.
- */
- i = 0;
- best = -1;
- PTY_SETUTXENT();
- while ((utxp = PTY_GETUTXLINE(search)) != NULL) {
- if (better(search, utxp, &utxtmp)) {
- utxtmp = *utxp;
- best = i;
- }
- memset(utxp, 0, sizeof(*utxp));
- i++;
- }
- if (best == -1)
- return NULL;
- PTY_SETUTXENT();
- for (i = 0; i <= best; i++) {
- if (utxp != NULL)
- memset(utxp, 0, sizeof(*utxp));
- utxp = PTY_GETUTXLINE(search);
- }
- return utxp;
-}
-
-/*
- * All calls to this function for a given login session must have the
- * pids be equal; various things will break if this is not the case,
- * since we do some searching based on the pid. Note that if a parent
- * process calls this via pty_cleanup(), it should still pass the
- * child's pid rather than its own.
- */
-long
-pty_update_utmp(int process_type, int pid, const char *username,
- const char *line, const char *host, int flags)
-{
- PTY_STRUCT_UTMPX utx, *utxtmp, utx2;
- const char *cp;
- size_t len;
- char utmp_id[5];
-
- /*
- * Zero things out in case there are fields we don't handle here.
- * They tend to be non-portable anyway.
- */
- memset(&utx, 0, sizeof(utx));
- utxtmp = NULL;
- cp = line;
- if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0)
- cp += sizeof("/dev/") - 1;
- strncpy(utx.ut_line, cp, sizeof(utx.ut_line));
- utx.ut_pid = pid;
- switch (process_type) {
- case PTY_LOGIN_PROCESS:
- utx.ut_type = LOGIN_PROCESS;
- break;
- case PTY_USER_PROCESS:
- utx.ut_type = USER_PROCESS;
- break;
- case PTY_DEAD_PROCESS:
- utx.ut_type = DEAD_PROCESS;
- break;
- default:
- return PTY_UPDATE_UTMP_PROCTYPE_INVALID;
- }
- len = strlen(line);
- if (len >= 2) {
- cp = line + len - 1;
- if (*(cp - 1) != '/')
- cp--; /* last two characters, unless it's a / */
- } else
- cp = line;
- /*
- * HP-UX has mostly 4-character inittab ids, while most other sysV
- * variants use only 2-charcter inittab ids, so to avoid
- * conflicts, we pick 2-character ut_ids for our own use. We may
- * want to feature-test for this, but it would be somewhat of a
- * pain, and would eit cross-compiling.
- */
-#ifdef __hpux
- strlcpy(utmp_id, cp, sizeof(utmp_id));
-#else
- if (len > 2 && *(cp - 1) != '/')
- snprintf(utmp_id, sizeof(utmp_id), "k%s", cp - 1);
- else
- snprintf(utmp_id, sizeof(utmp_id), "k0%s", cp);
-#endif
- strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id));
- /*
- * Get existing utmpx entry for PID or LINE, if any, so we can
- * copy some stuff from it. This is particularly important if we
- * are login.krb5 and are running out of getty, since getty will
- * have written the entry for the line with ut_type ==
- * LOGIN_PROCESS, and what it has recorded in ut_id may not be
- * what we come up with, since that's up to the whim of the
- * sysadmin who writes the inittab entry.
- *
- * Note that we may be screwed if we try to write a logout record
- * for a vendor's login program, since it may construct ut_line
- * and ut_id differently from us; even though we search on ut_pid,
- * we validate against ut_id or ut_line to sanity-check. We may
- * want to rethink whether to actually include this check, since
- * it should be highly unlikely that there will be a bogus entry
- * in utmpx matching our pid.
- */
- if (process_type != PTY_LOGIN_PROCESS)
- utxtmp = best_utxent(&utx);
-
-#ifdef HAVE_SETUTXENT
- if (gettimeofday(&utx.ut_tv, NULL))
- return errno;
-#else
- (void)time(&utx.ut_time);
-#endif
- /*
- * On what system is there not ut_host? Unix98 doesn't mandate
- * this field, but we have yet to see a system that supports utmpx
- * that doesn't have it. For what it's worth, some ancient utmp
- * headers on svr4 systems imply that there's no ut_host in struct
- * utmp...
- */
-#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST)) \
- || (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST))
- if (host != NULL) {
- strncpy(utx.ut_host, host, sizeof(utx.ut_host));
- /* Unlike other things in utmpx, ut_host is nul-terminated? */
- utx.ut_host[sizeof(utx.ut_host) - 1] = '\0';
- } else
- utx.ut_host[0] = '\0';
-#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_SYSLEN)) \
- || (!defined (HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_SYSLEN))
- if (host != NULL)
- utx.ut_syslen = strlen(utx.ut_host) + 1;
- else
- utx.ut_syslen = 0;
-#endif
-#endif
-
- /* XXX deal with ut_addr? */
-
- if (utxtmp != NULL) {
- /*
- * For entries not of type LOGIN_PROCESS, override some stuff
- * with what was in the previous entry we found, if any.
- */
- strncpy(utx.ut_id, utxtmp->ut_id, sizeof(utx.ut_id));
- utx.ut_pid = utxtmp->ut_pid;
- }
-
- strncpy(utx.ut_user, username, sizeof(utx.ut_user));
-
- /*
- * Make a copy now and deal with copying relevant things out of
- * utxtmp in case setutxline() or pututxline() clobbers utxtmp.
- * (After all, the returned pointer from the getutx*() functions
- * is allowed to point to static storage that may get overwritten
- * by subsequent calls to related functions.)
- */
- utx2 = utx;
- if (process_type == PTY_DEAD_PROCESS && utxtmp != NULL) {
- /*
- * Use ut_line from old entry to avoid confusing last on
- * HP-UX.
- */
- strncpy(utx2.ut_line, utxtmp->ut_line, sizeof(utx2.ut_line));
- }
-
- PTY_SETUTXENT();
- PTY_PUTUTXLINE(&utx);
- PTY_ENDUTXENT();
-
- /* Don't record LOGIN_PROCESS entries. */
- if (process_type == PTY_LOGIN_PROCESS)
- return 0;
-
-#ifdef HAVE_SETUTXENT
- return ptyint_update_wtmpx(&utx2);
-#else
- return ptyint_update_wtmp(&utx2);
-#endif
-}
-
-#else /* !(HAVE_SETUTXENT || HAVE_SETUTENT) */
-
-long
-pty_update_utmp(int process_type, int pid, const char *username,
- const char *line, const char *host, int flags)
-{
- struct utmp ent, ut;
- const char *cp;
- int tty, lc, fd;
- off_t seekpos;
- ssize_t ret;
- struct stat statb;
-
- memset(&ent, 0, sizeof(ent));
-#ifdef HAVE_STRUCT_UTMP_UT_HOST
- if (host)
- strncpy(ent.ut_host, host, sizeof(ent.ut_host));
-#endif
- strncpy(ent.ut_name, username, sizeof(ent.ut_name));
- cp = line;
- if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0)
- cp += sizeof("/dev/") - 1;
- strncpy(ent.ut_line, cp, sizeof(ent.ut_line));
- (void)time(&ent.ut_time);
-
- if (flags & PTY_TTYSLOT_USABLE)
- tty = ttyslot();
- else {
- tty = -1;
- fd = open(UTMP_FILE, O_RDONLY);
- if (fd == -1)
- return errno;
- for (lc = 0; ; lc++) {
- seekpos = lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET);
- if (seekpos != (off_t)(lc * sizeof(struct utmp)))
- break;
- if (read(fd, (char *) &ut, sizeof(struct utmp))
- != sizeof(struct utmp))
- break;
- if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
- tty = lc;
- break;
- }
- }
- close(fd);
- }
- if (tty > 0) {
- fd = open(UTMP_FILE, O_WRONLY);
- if (fd == -1)
- return 0;
- if (fstat(fd, &statb)) {
- close(fd);
- return 0;
- }
- seekpos = lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
- if (seekpos != (off_t)(tty * sizeof(struct utmp))) {
- close(fd);
- return 0;
- }
- ret = write(fd, (char *)&ent, sizeof(struct utmp));
- if (ret != sizeof(struct utmp)) {
- ftruncate(fd, statb.st_size);
- }
- close(fd);
- }
- /* Don't record LOGIN_PROCESS entries. */
- if (process_type == PTY_LOGIN_PROCESS)
- return 0;
- else
- return ptyint_update_wtmp(&ent);
-}
-#endif