2007-05-16 16:56:51 -05:00
|
|
|
/*
|
|
|
|
* Copyright 1990, 1998 The Open Group
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
* the above copyright notice appear in all copies and that both that
|
|
|
|
* copyright notice and this permission notice appear in supporting
|
|
|
|
* documentation.
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
* IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
* Except as contained in this notice, the name of The Open Group shall
|
|
|
|
* not be used in advertising or otherwise to promote the sale, use or
|
|
|
|
* other dealings in this Software without prior written authorization
|
|
|
|
* from The Open Group.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
2010-07-24 09:23:17 -05:00
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
2007-05-16 16:56:51 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Author: Keith Packard, MIT X Consortium
|
|
|
|
* Lastlog support and dynamic utmp entry allocation
|
|
|
|
* by Andreas Stolcke <stolcke@icsi.berkeley.edu>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sessreg
|
|
|
|
*
|
|
|
|
* simple wtmp/utmp frobber
|
|
|
|
*
|
|
|
|
* usage: sessreg [ -w <wtmp-file> ] [ -u <utmp-file> ]
|
|
|
|
* [ -l <line> ]
|
2009-12-06 06:02:51 -06:00
|
|
|
* [ -L <lastlog-file> ] / #ifndef NO_LASTLOG
|
2007-05-16 16:56:51 -05:00
|
|
|
* [ -h <host-name> ] / BSD only
|
|
|
|
* [ -s <slot-number> ] [ -x Xservers-file ] / BSD only
|
|
|
|
* [ -t <ttys-file> ] / BSD only
|
|
|
|
* [ -a ] [ -d ] user-name
|
|
|
|
*
|
|
|
|
* one of -a or -d must be specified
|
|
|
|
*/
|
|
|
|
|
2008-11-16 13:27:11 -06:00
|
|
|
#include "sessreg.h"
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
# include <X11/Xos.h>
|
|
|
|
# include <X11/Xfuncs.h>
|
|
|
|
# include <stdio.h>
|
|
|
|
# include <stdlib.h>
|
|
|
|
|
|
|
|
#if defined(__SVR4) || defined(SVR4) || defined(linux) || defined(__GLIBC__)
|
2008-11-16 13:27:11 -06:00
|
|
|
# define SYSV
|
2007-05-16 16:56:51 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#define Time_t time_t
|
|
|
|
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
|
|
|
static void set_utmp (struct utmp *u, char *line, char *user, char *host,
|
|
|
|
Time_t date, int addp);
|
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
#ifdef USE_UTMPX
|
|
|
|
static void set_utmpx (struct utmpx *u, const char *line, const char *user,
|
|
|
|
const char *host, Time_t date, int addp);
|
|
|
|
#endif
|
|
|
|
|
2010-11-12 12:26:44 -06:00
|
|
|
#ifdef SYSV
|
|
|
|
/* used for hashing ut_id */
|
|
|
|
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
|
|
|
|
typedef unsigned char ub1; /* unsigned 1-byte quantities */
|
|
|
|
|
|
|
|
#define hashsize(n) ((ub4)1<<(n))
|
|
|
|
#define hashmask(n) (hashsize(n)-1)
|
|
|
|
|
|
|
|
ub4 hash(register ub1 *k, register ub4 length, register ub4 initval);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2009-12-06 06:02:51 -06:00
|
|
|
static int wflag, uflag, lflag;
|
|
|
|
static char *wtmp_file, *utmp_file, *line;
|
2007-05-16 16:56:51 -05:00
|
|
|
#ifdef USE_UTMPX
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef HAVE_UPDWTMPX
|
|
|
|
static char *wtmpx_file = NULL;
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_UTMPXNAME
|
|
|
|
static char *utmpx_file = NULL;
|
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
#endif
|
2009-12-06 06:02:51 -06:00
|
|
|
static int utmp_none, wtmp_none;
|
2007-05-16 16:56:51 -05:00
|
|
|
/*
|
|
|
|
* BSD specific variables. To make life much easier for Xstartup/Xreset
|
|
|
|
* maintainers, these arguments are accepted but ignored for sysV
|
|
|
|
*/
|
2009-12-06 06:02:51 -06:00
|
|
|
static int hflag, sflag, xflag, tflag;
|
|
|
|
static char *host_name = NULL;
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
2009-12-06 06:02:51 -06:00
|
|
|
static int slot_number;
|
2010-07-24 09:23:17 -05:00
|
|
|
#endif
|
2009-12-06 06:02:51 -06:00
|
|
|
static char *xservers_file, *ttys_file;
|
|
|
|
static char *user_name;
|
|
|
|
static int aflag, dflag;
|
2007-05-16 16:56:51 -05:00
|
|
|
#ifndef NO_LASTLOG
|
2009-12-06 06:02:51 -06:00
|
|
|
static char *llog_file;
|
|
|
|
static int llog_none, Lflag;
|
2007-05-16 16:56:51 -05:00
|
|
|
#endif
|
|
|
|
|
2009-12-06 06:02:51 -06:00
|
|
|
static char *program_name;
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
#ifndef SYSV
|
|
|
|
static int findslot (char *line_name, char *host_name, int addp, int slot);
|
|
|
|
static int Xslot (char *ttys_file, char *servers_file, char *tty_line,
|
|
|
|
char *host_name, int addp);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
|
|
|
usage (int x)
|
|
|
|
{
|
|
|
|
if (x) {
|
|
|
|
fprintf (stderr, "%s: usage %s {-a -d} [-w wtmp-file] [-u utmp-file]", program_name, program_name);
|
|
|
|
#ifndef NO_LASTLOG
|
|
|
|
fprintf (stderr, " [-L lastlog-file]");
|
|
|
|
#endif
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
fprintf (stderr, " [-t ttys-file] [-l line-name] [-h host-name]\n");
|
|
|
|
fprintf (stderr, " [-s slot-number] [-x servers-file] user-name\n");
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
getstring (char ***avp, int *flagp)
|
|
|
|
{
|
|
|
|
char **a = *avp;
|
|
|
|
|
|
|
|
usage ((*flagp)++);
|
|
|
|
if (*++*a)
|
|
|
|
return *a;
|
|
|
|
++a;
|
|
|
|
usage (!*a);
|
|
|
|
*avp = a;
|
|
|
|
return *a;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef SYSV
|
|
|
|
static int
|
|
|
|
syserr (int x, const char *s)
|
|
|
|
{
|
|
|
|
if (x == -1) {
|
|
|
|
perror (s);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
|
|
|
sysnerr (int x, const char *s)
|
|
|
|
{
|
|
|
|
if (x == 0) {
|
|
|
|
perror (s);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
|
|
|
{
|
2010-07-24 09:23:17 -05:00
|
|
|
#if defined(USE_UTMP) && !defined(SYSV)
|
2007-05-16 16:56:51 -05:00
|
|
|
int utmp;
|
|
|
|
#endif
|
|
|
|
char *line_tmp;
|
2008-11-16 13:27:11 -06:00
|
|
|
#ifndef USE_UTMPX
|
2007-05-16 16:56:51 -05:00
|
|
|
int wtmp;
|
2008-11-16 13:27:11 -06:00
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
Time_t current_time;
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
2007-05-16 16:56:51 -05:00
|
|
|
struct utmp utmp_entry;
|
2010-07-24 09:23:17 -05:00
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
#ifdef USE_UTMPX
|
|
|
|
struct utmpx utmpx_entry;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
program_name = argv[0];
|
|
|
|
while (*++argv && **argv == '-') {
|
|
|
|
switch (*++*argv) {
|
|
|
|
case 'w':
|
|
|
|
wtmp_file = getstring (&argv, &wflag);
|
|
|
|
if (!strcmp (wtmp_file, "none"))
|
|
|
|
wtmp_none = 1;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
utmp_file = getstring (&argv, &uflag);
|
|
|
|
if (!strcmp (utmp_file, "none"))
|
|
|
|
utmp_none = 1;
|
|
|
|
break;
|
|
|
|
#ifndef NO_LASTLOG
|
|
|
|
case 'L':
|
|
|
|
llog_file = getstring (&argv, &Lflag);
|
|
|
|
if (!strcmp (llog_file, "none"))
|
|
|
|
llog_none = 1;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 't':
|
|
|
|
ttys_file = getstring (&argv, &tflag);
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
line = getstring (&argv, &lflag);
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
host_name = getstring (&argv, &hflag);
|
|
|
|
break;
|
|
|
|
case 's':
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
2007-05-16 16:56:51 -05:00
|
|
|
slot_number = atoi (getstring (&argv, &sflag));
|
2010-07-24 09:23:17 -05:00
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
xservers_file = getstring (&argv, &xflag);
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
aflag++;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
dflag++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage (1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
usage (!(user_name = *argv++));
|
2009-12-06 06:02:51 -06:00
|
|
|
usage (*argv != NULL);
|
2007-05-16 16:56:51 -05:00
|
|
|
/*
|
|
|
|
* complain if neither aflag nor dflag are set,
|
|
|
|
* or if both are set.
|
|
|
|
*/
|
|
|
|
usage (!(aflag ^ dflag));
|
|
|
|
usage (xflag && !lflag);
|
|
|
|
/* set up default file names */
|
|
|
|
if (!wflag) {
|
|
|
|
wtmp_file = WTMP_FILE;
|
2010-07-24 09:23:17 -05:00
|
|
|
#if defined(USE_UTMPX) && defined(HAVE_UPDWTMPX)
|
2007-05-16 16:56:51 -05:00
|
|
|
wtmpx_file = WTMPX_FILE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifndef NO_UTMP
|
|
|
|
if (!uflag) {
|
|
|
|
utmp_file = UTMP_FILE;
|
2010-07-24 09:23:17 -05:00
|
|
|
#if defined(USE_UTMPX) && defined(HAVE_UTMPXNAME)
|
2007-05-16 16:56:51 -05:00
|
|
|
utmpx_file = UTMPX_FILE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
utmp_none = 1;
|
|
|
|
#endif
|
|
|
|
#ifndef NO_LASTLOG
|
|
|
|
if (!Lflag)
|
|
|
|
llog_file = LLOG_FILE;
|
|
|
|
#endif
|
2010-07-24 09:23:17 -05:00
|
|
|
#if defined(USE_UTMP) && !defined(SYSV) && !defined(linux) && !defined(__QNX__)
|
2007-05-16 16:56:51 -05:00
|
|
|
if (!tflag)
|
|
|
|
ttys_file = TTYS_FILE;
|
|
|
|
if (!sflag && !utmp_none) {
|
|
|
|
if (xflag)
|
|
|
|
sysnerr (slot_number = Xslot (ttys_file, xservers_file, line, host_name, aflag), "Xslot");
|
|
|
|
else
|
|
|
|
sysnerr (slot_number = ttyslot (), "ttyslot");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!lflag) {
|
|
|
|
sysnerr ((line_tmp = ttyname (0)) != NULL, "ttyname");
|
|
|
|
line = strrchr(line_tmp, '/');
|
|
|
|
if (line)
|
|
|
|
line = line + 1;
|
|
|
|
else
|
|
|
|
line = line_tmp;
|
|
|
|
}
|
|
|
|
time (¤t_time);
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
2007-05-16 16:56:51 -05:00
|
|
|
set_utmp (&utmp_entry, line, user_name, host_name, current_time, aflag);
|
2010-07-24 09:23:17 -05:00
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
#ifdef USE_UTMPX
|
|
|
|
/* need to set utmpxname() before calling set_utmpx() for
|
|
|
|
UtmpxIdOpen to work */
|
2010-07-24 09:23:17 -05:00
|
|
|
# ifdef HAVE_UTMPXNAME
|
2007-05-16 16:56:51 -05:00
|
|
|
if (utmpx_file != NULL) {
|
|
|
|
utmpxname (utmpx_file);
|
|
|
|
}
|
2010-07-24 09:23:17 -05:00
|
|
|
# endif
|
2007-05-16 16:56:51 -05:00
|
|
|
set_utmpx (&utmpx_entry, line, user_name,
|
|
|
|
host_name, current_time, aflag);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!utmp_none) {
|
|
|
|
#ifdef USE_UTMPX
|
2010-07-24 09:23:17 -05:00
|
|
|
# ifdef HAVE_UTMPX_NAME
|
|
|
|
if (utmpx_file != NULL)
|
|
|
|
# endif
|
|
|
|
{
|
2007-05-16 16:56:51 -05:00
|
|
|
setutxent ();
|
|
|
|
(void) getutxid (&utmpx_entry);
|
|
|
|
pututxline (&utmpx_entry);
|
|
|
|
endutxent ();
|
|
|
|
}
|
|
|
|
#endif
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
|
|
|
# ifdef SYSV
|
2007-05-16 16:56:51 -05:00
|
|
|
utmpname (utmp_file);
|
|
|
|
setutent ();
|
|
|
|
(void) getutid (&utmp_entry);
|
|
|
|
pututline (&utmp_entry);
|
|
|
|
endutent ();
|
2010-07-24 09:23:17 -05:00
|
|
|
# else
|
2007-05-16 16:56:51 -05:00
|
|
|
utmp = open (utmp_file, O_RDWR);
|
|
|
|
if (utmp != -1) {
|
|
|
|
syserr ((int) lseek (utmp, (long) slot_number * sizeof (struct utmp), 0), "lseek");
|
|
|
|
sysnerr (write (utmp, (char *) &utmp_entry, sizeof (utmp_entry))
|
|
|
|
== sizeof (utmp_entry), "write utmp entry");
|
|
|
|
close (utmp);
|
|
|
|
}
|
2010-07-24 09:23:17 -05:00
|
|
|
# endif
|
|
|
|
#endif /* USE_UTMP */
|
2007-05-16 16:56:51 -05:00
|
|
|
}
|
|
|
|
if (!wtmp_none) {
|
|
|
|
#ifdef USE_UTMPX
|
2010-07-24 09:23:17 -05:00
|
|
|
# ifdef HAVE_UPDWTMPX
|
2007-05-16 16:56:51 -05:00
|
|
|
if (wtmpx_file != NULL) {
|
|
|
|
updwtmpx(wtmpx_file, &utmpx_entry);
|
|
|
|
}
|
2010-07-24 09:23:17 -05:00
|
|
|
# endif
|
2007-05-16 16:56:51 -05:00
|
|
|
#else
|
|
|
|
wtmp = open (wtmp_file, O_WRONLY|O_APPEND);
|
|
|
|
if (wtmp != -1) {
|
|
|
|
sysnerr (write (wtmp, (char *) &utmp_entry, sizeof (utmp_entry))
|
|
|
|
== sizeof (utmp_entry), "write wtmp entry");
|
|
|
|
close (wtmp);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifndef NO_LASTLOG
|
|
|
|
if (aflag && !llog_none) {
|
|
|
|
int llog;
|
|
|
|
struct passwd *pwd = getpwnam(user_name);
|
|
|
|
|
|
|
|
sysnerr( pwd != NULL, "get user id");
|
|
|
|
llog = open (llog_file, O_RDWR);
|
|
|
|
|
|
|
|
if (llog != -1) {
|
|
|
|
struct lastlog ll;
|
|
|
|
|
|
|
|
sysnerr (lseek(llog, (long) pwd->pw_uid*sizeof(ll), 0)
|
|
|
|
!= -1, "seeking lastlog entry");
|
|
|
|
bzero((char *)&ll, sizeof(ll));
|
|
|
|
ll.ll_time = current_time;
|
|
|
|
if (line)
|
|
|
|
(void) strncpy (ll.ll_line, line, sizeof (ll.ll_line));
|
|
|
|
if (host_name)
|
|
|
|
(void) strncpy (ll.ll_host, host_name, sizeof (ll.ll_host));
|
|
|
|
|
|
|
|
sysnerr (write (llog, (char *) &ll, sizeof (ll))
|
|
|
|
== sizeof (ll), "write lastlog entry");
|
|
|
|
close (llog);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* fill in the appropriate records of the utmp entry
|
|
|
|
*/
|
|
|
|
|
2010-07-24 09:23:17 -05:00
|
|
|
#ifdef USE_UTMP
|
2007-05-16 16:56:51 -05:00
|
|
|
static void
|
|
|
|
set_utmp (struct utmp *u, char *line, char *user, char *host, Time_t date, int addp)
|
|
|
|
{
|
|
|
|
bzero (u, sizeof (*u));
|
|
|
|
if (line)
|
|
|
|
(void) strncpy (u->ut_line, line, sizeof (u->ut_line));
|
|
|
|
else
|
|
|
|
bzero (u->ut_line, sizeof (u->ut_line));
|
|
|
|
if (addp && user)
|
|
|
|
(void) strncpy (u->ut_name, user, sizeof (u->ut_name));
|
|
|
|
else
|
|
|
|
bzero (u->ut_name, sizeof (u->ut_name));
|
|
|
|
#ifdef SYSV
|
|
|
|
if (line) {
|
|
|
|
/*
|
2010-11-12 12:26:44 -06:00
|
|
|
* The ut_id is 4 bytes long. We make a hash of the line
|
|
|
|
* received, preceding it by ":" to prevent clashing with
|
|
|
|
* other ut_ids.
|
2007-05-16 16:56:51 -05:00
|
|
|
*/
|
2010-11-12 12:26:44 -06:00
|
|
|
ub4 h;
|
|
|
|
u->ut_id[0]=':';
|
|
|
|
h = hash(line, strlen(line),0x9e3779b9);
|
|
|
|
h = (h & hashmask((sizeof(u->ut_id)-sizeof(char))*8));
|
|
|
|
(void) strncpy (u->ut_id + 1,(char *) &h, sizeof (u->ut_id)-sizeof(char));
|
2007-05-16 16:56:51 -05:00
|
|
|
} else
|
2010-11-12 12:26:44 -06:00
|
|
|
/*
|
|
|
|
* From utmp(5):
|
|
|
|
* Clearing ut_id may result in race conditions leading to corrupted
|
|
|
|
* utmp entries and and potential security holes.
|
|
|
|
*/
|
|
|
|
/* TODO: CHECK this */
|
2007-05-16 16:56:51 -05:00
|
|
|
bzero (u->ut_id, sizeof (u->ut_id));
|
|
|
|
if (addp) {
|
|
|
|
u->ut_pid = getppid ();
|
|
|
|
u->ut_type = USER_PROCESS;
|
|
|
|
} else {
|
|
|
|
u->ut_pid = 0;
|
|
|
|
u->ut_type = DEAD_PROCESS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if (!defined(SYSV) && !defined(__QNX__)) || defined(linux)
|
|
|
|
if (addp && host)
|
|
|
|
(void) strncpy (u->ut_host, host, sizeof (u->ut_host));
|
|
|
|
else
|
|
|
|
bzero (u->ut_host, sizeof (u->ut_host));
|
|
|
|
#endif
|
|
|
|
u->ut_time = date;
|
|
|
|
}
|
2010-07-24 09:23:17 -05:00
|
|
|
#endif /* USE_UTMP */
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
#ifdef USE_UTMPX
|
|
|
|
static int
|
|
|
|
UtmpxIdOpen( char *utmpId )
|
|
|
|
{
|
|
|
|
struct utmpx *u; /* pointer to entry in utmp file */
|
|
|
|
int status = 1; /* return code */
|
2010-07-24 09:23:17 -05:00
|
|
|
|
|
|
|
setutxent();
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
while ( (u = getutxent()) != NULL ) {
|
|
|
|
|
|
|
|
if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
|
|
|
|
u->ut_type != DEAD_PROCESS ) {
|
|
|
|
|
|
|
|
status = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-24 09:23:17 -05:00
|
|
|
endutxent();
|
2007-05-16 16:56:51 -05:00
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_utmpx (struct utmpx *u, const char *line, const char *user,
|
|
|
|
const char *host, Time_t date, int addp)
|
|
|
|
{
|
|
|
|
static const char letters[] =
|
|
|
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
|
|
|
|
if (line)
|
|
|
|
{
|
|
|
|
if(strcmp(line, ":0") == 0)
|
|
|
|
(void) strcpy(u->ut_line, "console");
|
|
|
|
else
|
|
|
|
(void) strncpy (u->ut_line, line, sizeof (u->ut_line));
|
|
|
|
|
|
|
|
strncpy(u->ut_host, line, sizeof(u->ut_host));
|
2010-07-24 09:23:17 -05:00
|
|
|
#if HAVE_UTMPX_UT_SYSLEN
|
2007-05-16 16:56:51 -05:00
|
|
|
u->ut_syslen = strlen(line);
|
2010-07-24 09:23:17 -05:00
|
|
|
#endif
|
2007-05-16 16:56:51 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
bzero (u->ut_line, sizeof (u->ut_line));
|
|
|
|
if (addp && user)
|
2010-07-24 09:23:17 -05:00
|
|
|
(void) strncpy (u->ut_user, user, sizeof (u->ut_user));
|
2007-05-16 16:56:51 -05:00
|
|
|
else
|
2010-07-24 09:23:17 -05:00
|
|
|
bzero (u->ut_user, sizeof (u->ut_user));
|
2007-05-16 16:56:51 -05:00
|
|
|
|
|
|
|
if (line) {
|
|
|
|
int i;
|
|
|
|
/*
|
|
|
|
* this is a bit crufty, but
|
|
|
|
* follows the apparent conventions in
|
|
|
|
* the ttys file. ut_id is only 4 bytes
|
|
|
|
* long, and the last 4 bytes of the line
|
|
|
|
* name are written into it, left justified.
|
|
|
|
*/
|
|
|
|
i = strlen (line);
|
|
|
|
if (i >= sizeof (u->ut_id))
|
|
|
|
i -= sizeof (u->ut_id);
|
|
|
|
else
|
|
|
|
i = 0;
|
|
|
|
(void) strncpy (u->ut_id, line + i, sizeof (u->ut_id));
|
|
|
|
|
|
|
|
/* make sure there is no entry using identical ut_id */
|
|
|
|
if (!UtmpxIdOpen(u->ut_id) && addp) {
|
|
|
|
int limit = sizeof(letters) - 1;
|
|
|
|
int t = 0;
|
|
|
|
|
|
|
|
u->ut_id[1] = line[i];
|
|
|
|
u->ut_id[2] = line[i+1];
|
|
|
|
u->ut_id[3] = line[i+2];
|
|
|
|
do {
|
|
|
|
u->ut_id[0] = letters[t];
|
|
|
|
t++;
|
|
|
|
} while (!UtmpxIdOpen(u->ut_id) && (t < limit));
|
|
|
|
}
|
|
|
|
if (!addp && strstr(line, ":") != NULL) {
|
|
|
|
struct utmpx *tmpu;
|
|
|
|
|
|
|
|
while ( (tmpu = getutxent()) != NULL ) {
|
|
|
|
if ( (strcmp(tmpu->ut_host, line) == 0 ) &&
|
|
|
|
tmpu->ut_type != DEAD_PROCESS ) {
|
|
|
|
strncpy(u->ut_id, tmpu->ut_id,
|
|
|
|
sizeof(u->ut_id));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endutxent();
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
bzero (u->ut_id, sizeof (u->ut_id));
|
|
|
|
|
|
|
|
if (addp) {
|
|
|
|
u->ut_pid = getppid ();
|
|
|
|
u->ut_type = USER_PROCESS;
|
|
|
|
} else {
|
|
|
|
u->ut_pid = 0;
|
|
|
|
u->ut_type = DEAD_PROCESS;
|
|
|
|
}
|
|
|
|
u->ut_tv.tv_sec = date;
|
|
|
|
u->ut_tv.tv_usec = 0;
|
|
|
|
}
|
|
|
|
#endif /* USE_UTMPX */
|
|
|
|
|
2010-07-24 09:23:17 -05:00
|
|
|
#if defined(USE_UTMP) && !defined(SYSV)
|
2007-05-16 16:56:51 -05:00
|
|
|
/*
|
|
|
|
* compute the slot-number for an X display. This is computed
|
|
|
|
* by counting the lines in /etc/ttys and adding the line-number
|
|
|
|
* that the display appears on in Xservers. This is a poor
|
|
|
|
* design, but is limited by the non-existant interface to utmp.
|
|
|
|
* If host_name is non-NULL, assume it contains the display name,
|
|
|
|
* otherwise use the tty_line argument (i.e., the tty name).
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
Xslot (char *ttys_file, char *servers_file, char *tty_line, char *host_name,
|
|
|
|
int addp)
|
|
|
|
{
|
|
|
|
FILE *ttys, *servers;
|
|
|
|
int c;
|
|
|
|
int slot = 1;
|
|
|
|
int column0 = 1;
|
|
|
|
char servers_line[1024];
|
|
|
|
char disp_name[512];
|
|
|
|
int len;
|
|
|
|
char *pos;
|
|
|
|
|
|
|
|
/* remove screen number from the display name */
|
|
|
|
memset(disp_name, 0, sizeof(disp_name));
|
|
|
|
strncpy(disp_name, host_name ? host_name : tty_line, sizeof(disp_name)-1);
|
|
|
|
pos = strrchr(disp_name, ':');
|
|
|
|
if (pos) {
|
|
|
|
pos = strchr(pos, '.');
|
|
|
|
if (pos)
|
|
|
|
*pos = '\0';
|
|
|
|
}
|
|
|
|
sysnerr ((int)(long)(ttys = fopen (ttys_file, "r")), ttys_file);
|
|
|
|
while ((c = getc (ttys)) != EOF)
|
|
|
|
if (c == '\n') {
|
|
|
|
++slot;
|
|
|
|
column0 = 1;
|
|
|
|
} else
|
|
|
|
column0 = 0;
|
|
|
|
if (!column0)
|
|
|
|
++slot;
|
|
|
|
(void) fclose (ttys);
|
|
|
|
sysnerr ((int)(long)(servers = fopen (servers_file, "r")), servers_file);
|
|
|
|
|
|
|
|
len = strlen (disp_name);
|
|
|
|
column0 = 1;
|
|
|
|
while (fgets (servers_line, sizeof (servers_line), servers)) {
|
|
|
|
if (column0 && *servers_line != '#') {
|
|
|
|
if (!strncmp (disp_name, servers_line, len) &&
|
|
|
|
(servers_line[len] == ' ' ||
|
|
|
|
servers_line[len] == '\t'))
|
|
|
|
return slot;
|
|
|
|
++slot;
|
|
|
|
}
|
|
|
|
if (servers_line[strlen(servers_line)-1] != '\n')
|
|
|
|
column0 = 0;
|
|
|
|
else
|
|
|
|
column0 = 1;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* display not found in Xservers file - allocate utmp entry dinamically
|
|
|
|
*/
|
|
|
|
return findslot (tty_line, host_name, addp, slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* find a free utmp slot for the X display. This allocates a new entry
|
|
|
|
* past the regular tty entries if necessary, reusing existing entries
|
|
|
|
* (identified by (line,hostname)) if possible.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
findslot (char *line_name, char *host_name, int addp, int slot)
|
|
|
|
{
|
|
|
|
int utmp;
|
|
|
|
struct utmp entry;
|
|
|
|
int found = 0;
|
|
|
|
int freeslot = -1;
|
|
|
|
|
|
|
|
syserr(utmp = open (utmp_file, O_RDONLY), "open utmp");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* first, try to locate a previous entry for this display
|
|
|
|
* also record location of a free slots in case we need a new one
|
|
|
|
*/
|
|
|
|
syserr ((int) lseek (utmp, (long) slot * sizeof (struct utmp), 0), "lseek");
|
|
|
|
|
|
|
|
if (!host_name)
|
|
|
|
host_name = "";
|
|
|
|
|
|
|
|
while (read (utmp, (char *) &entry, sizeof (entry)) == sizeof (entry)) {
|
|
|
|
if (strncmp(entry.ut_line, line_name,
|
|
|
|
sizeof(entry.ut_line)) == 0
|
|
|
|
#ifndef __QNX__
|
|
|
|
&&
|
|
|
|
strncmp(entry.ut_host, host_name,
|
|
|
|
sizeof(entry.ut_host)) == 0
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (freeslot < 0 && *entry.ut_name == '\0')
|
|
|
|
freeslot = slot;
|
|
|
|
++slot;
|
|
|
|
}
|
|
|
|
|
|
|
|
close (utmp);
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
return slot;
|
|
|
|
else if (!addp)
|
|
|
|
return 0; /* trying to delete a non-existing entry */
|
|
|
|
else if (freeslot < 0)
|
|
|
|
return slot; /* first slot past current entries */
|
|
|
|
else
|
|
|
|
return freeslot;
|
|
|
|
}
|
|
|
|
#endif
|
2010-11-12 12:26:44 -06:00
|
|
|
|
|
|
|
#ifdef SYSV
|
|
|
|
/*
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
mix -- mix 3 32-bit values reversibly.
|
|
|
|
For every delta with one or two bits set, and the deltas of all three
|
|
|
|
high bits or all three low bits, whether the original value of a,b,c
|
|
|
|
is almost all zero or is uniformly distributed,
|
|
|
|
* If mix() is run forward or backward, at least 32 bits in a,b,c
|
|
|
|
have at least 1/4 probability of changing.
|
|
|
|
* If mix() is run forward, every bit of c will change between 1/3 and
|
|
|
|
2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
|
|
|
|
mix() was built out of 36 single-cycle latency instructions in a
|
|
|
|
structure that could supported 2x parallelism, like so:
|
|
|
|
a -= b;
|
|
|
|
a -= c; x = (c>>13);
|
|
|
|
b -= c; a ^= x;
|
|
|
|
b -= a; x = (a<<8);
|
|
|
|
c -= a; b ^= x;
|
|
|
|
c -= b; x = (b>>13);
|
|
|
|
...
|
|
|
|
Unfortunately, superscalar Pentiums and Sparcs can't take advantage
|
|
|
|
of that parallelism. They've also turned some of those single-cycle
|
|
|
|
latency instructions into multi-cycle latency instructions. Still,
|
|
|
|
this is the fastest good hash I could find. There were about 2^^68
|
|
|
|
to choose from. I only looked at a billion or so.
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#define mix(a,b,c) \
|
|
|
|
{ \
|
|
|
|
a -= b; a -= c; a ^= (c>>13); \
|
|
|
|
b -= c; b -= a; b ^= (a<<8); \
|
|
|
|
c -= a; c -= b; c ^= (b>>13); \
|
|
|
|
a -= b; a -= c; a ^= (c>>12); \
|
|
|
|
b -= c; b -= a; b ^= (a<<16); \
|
|
|
|
c -= a; c -= b; c ^= (b>>5); \
|
|
|
|
a -= b; a -= c; a ^= (c>>3); \
|
|
|
|
b -= c; b -= a; b ^= (a<<10); \
|
|
|
|
c -= a; c -= b; c ^= (b>>15); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
hash() -- hash a variable-length key into a 32-bit value
|
|
|
|
k : the key (the unaligned variable-length array of bytes)
|
|
|
|
len : the length of the key, counting by bytes
|
|
|
|
initval : can be any 4-byte value
|
|
|
|
Returns a 32-bit value. Every bit of the key affects every bit of
|
|
|
|
the return value. Every 1-bit and 2-bit delta achieves avalanche.
|
|
|
|
About 6*len+35 instructions.
|
|
|
|
|
|
|
|
The best hash table sizes are powers of 2. There is no need to do
|
|
|
|
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
|
|
|
use a bitmask. For example, if you need only 10 bits, do
|
|
|
|
h = (h & hashmask(10));
|
|
|
|
In which case, the hash table should have hashsize(10) elements.
|
|
|
|
|
|
|
|
If you are hashing n strings (ub1 **)k, do it like this:
|
|
|
|
for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
|
|
|
|
|
|
|
|
By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
|
|
|
|
code any way you wish, private, educational, or commercial. It's free.
|
|
|
|
|
|
|
|
[On 27 May 2004, Bob Jenkins further clarified the above statement.
|
|
|
|
|
|
|
|
From: Bob Jenkins <bob_jenkins@burtleburtle.net>
|
|
|
|
Date: Thu, 27 May 2004 22:33:06 -0700
|
|
|
|
To: Margarita Manterola <marga@marga.com.ar>
|
|
|
|
Subject: Re: Hash function
|
|
|
|
|
|
|
|
The algorithm is public domain. I ask that I be referenced as the
|
|
|
|
source of the algorithm, but I can't enforce that, since being public
|
|
|
|
domain means I've reserved no rights at all.
|
|
|
|
|
|
|
|
-- Branden Robinson, 2004-06-06]
|
|
|
|
|
|
|
|
See http://burtleburtle.net/bob/hash/evahash.html
|
|
|
|
Use for hash table lookup, or anything where one collision in 2^^32 is
|
|
|
|
acceptable. Do NOT use for cryptographic purposes.
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
ub4
|
|
|
|
hash(register ub1 *k, register ub4 length, register ub4 initval)
|
|
|
|
{
|
|
|
|
register ub4 a,b,c,len;
|
|
|
|
|
|
|
|
/* Set up the internal state */
|
|
|
|
len = length;
|
|
|
|
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
|
|
|
c = initval; /* the previous hash value */
|
|
|
|
|
|
|
|
/*---------------------------------------- handle most of the key */
|
|
|
|
while (len >= 12)
|
|
|
|
{
|
|
|
|
a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
|
|
|
|
b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
|
|
|
|
c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
|
|
|
|
mix(a,b,c);
|
|
|
|
k += 12; len -= 12;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------- handle the last 11 bytes */
|
|
|
|
c += length;
|
|
|
|
switch(len) /* all the case statements fall through */
|
|
|
|
{
|
|
|
|
case 11: c+=((ub4)k[10]<<24);
|
|
|
|
case 10: c+=((ub4)k[9]<<16);
|
|
|
|
case 9 : c+=((ub4)k[8]<<8);
|
|
|
|
/* the first byte of c is reserved for the length */
|
|
|
|
case 8 : b+=((ub4)k[7]<<24);
|
|
|
|
case 7 : b+=((ub4)k[6]<<16);
|
|
|
|
case 6 : b+=((ub4)k[5]<<8);
|
|
|
|
case 5 : b+=k[4];
|
|
|
|
case 4 : a+=((ub4)k[3]<<24);
|
|
|
|
case 3 : a+=((ub4)k[2]<<16);
|
|
|
|
case 2 : a+=((ub4)k[1]<<8);
|
|
|
|
case 1 : a+=k[0];
|
|
|
|
/* case 0: nothing left to add */
|
|
|
|
}
|
|
|
|
mix(a,b,c);
|
|
|
|
/*-------------------------------------------- report the result */
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|