/* This file is part of GNU Pies.
Copyright (C) 2013 Sergey Poznyakoff
GNU Pies is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Pies is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Pies. If not, see . */
#include "pies.h"
#include
#include
#include
#ifdef HAVE_UTMPX_H
# include
typedef struct utmpx UTMPX;
# if HAVE_UPDWTMPX
# define pies_updwtmpx updwtmpx
# endif
# define GETUTXID getutxid
# undef UTMP_FILE
# define UTMP_FILE UTMPX_FILE
# undef WTMP_FILE
# define WTMP_FILE WTMPX_FILE
# if defined HAVE_STRUCT_UTMPX_UT_NAME
# define UT_NAME(u) ((u)->ut_name)
# elif defined HAVE_STRUCT_UTMPX_UT_USER
# define UT_NAME(u) ((u)->ut_user)
# endif
#else
# include
typedef struct utmp UTMPX;
# if defined HAVE_STRUCT_UTMP_UT_NAME
# define UT_NAME(u) ((u)->ut_name)
# elif defined HAVE_STRUCT_UTMP_UT_USER
# define UT_NAME(u) ((u)->ut_user)
# endif
# if HAVE_UPDWTMP
# define pies_updwtmpx updwtmp
# endif
# define GETUTXID getutid
# define setutxent setutent
# define pututxline pututline
# define endutxent endutent
#endif
#ifndef pies_updwtmpx
static void
pies_updwtmpx (const char *wtmp_file, const UTMPX *ut)
{
int fd = open (wtmp_file, O_WRONLY|O_APPEND);
if (fd == -1)
return;
if (write (fd, ut, sizeof (*ut)) == -1)
logmsg (LOG_ERR, "write %s: %s", wtmp_file, strerror (errno));
close (fd);
}
#endif
static UTMPX *
pies_getutxid (const UTMPX *ut)
{
static UTMPX tmp;
memcpy (&tmp, ut, sizeof (*ut));
return GETUTXID (&tmp);
}
void
fill_utmp (UTMPX *utmp,
int type, const char *user, const char *id, pid_t pid,
const char *line)
{
#if defined HAVE_STRUCT_UTMP_UT_HOST
struct utsname uts;
#endif
#if defined HAVE_STRUCT_UTMP_UT_TV
struct timeval tv;
#endif
memset (utmp, 0, sizeof (*utmp));
#if defined(HAVE_STRUCT_UTMP_UT_TV) || defined(HAVE_STRUCT_UTMPX_UT_TV)
gettimeofday (&tv, 0);
utmp->ut_tv.tv_sec = tv.tv_sec;
utmp->ut_tv.tv_usec = tv.tv_usec;
#elif defined(HAVE_STRUCT_UTMP_UT_TIME) || defined(HAVE_STRUCT_UTMPX_UT_TIME)
time (&utmp->ut_time);
#endif
utmp->ut_type = type;
strncpy (UT_NAME (utmp), user, sizeof (UT_NAME (utmp)));
strncpy (utmp->ut_id, id, sizeof (utmp->ut_id));
utmp->ut_pid = pid;
strncpy (utmp->ut_line, line, sizeof(utmp->ut_line));
#if defined(HAVE_STRUCT_UTMP_UT_HOST) || defined(HAVE_STRUCT_UTMPX_UT_HOST)
if (uname (&uts) == 0)
strncpy (utmp->ut_host, uts.release, sizeof(utmp->ut_host));
#endif
}
void
write_wtmpx (int type, const char *user, const char *id, pid_t pid,
const char *line)
{
UTMPX utmp;
static int wtmpxreboot = 0;
debug (2, (_("cannot open %s for writing"), WTMP_FILE));
if (access (WTMP_FILE, W_OK))
{
if (type == BOOT_TIME)
wtmpxreboot++;
return;
}
if (wtmpxreboot)
{
write_wtmpx (BOOT_TIME, "reboot", "~~", 0, "~");
--wtmpxreboot;
}
fill_utmp (&utmp, type, user, id, pid, line);
pies_updwtmpx (WTMP_FILE, &utmp);
}
void
write_utmpx (int type, const char *user, const char *id, pid_t pid,
const char *line)
{
UTMPX utmp;
static int utmpreboot = 0;
if (access (UTMP_FILE, W_OK))
{
debug (1, (_("cannot open %s for writing"), UTMP_FILE));
if (type == BOOT_TIME)
utmpreboot++;
return;
}
if (utmpreboot)
{
write_utmpx (BOOT_TIME, "reboot", "~~", 0, "~");
--utmpreboot;
}
fill_utmp (&utmp, type, user, id, pid, line);
if (type == DEAD_PROCESS)
{
UTMPX *p = pies_getutxid (&utmp);
if (p)
strncpy (utmp.ut_line, p->ut_line, sizeof (utmp.ut_line));
}
setutxent ();
pututxline (&utmp);
endutxent ();
}
void
sysvinit_acct (int what, const char *user, const char *id, pid_t pid,
const char *line)
{
static int types[] = {
BOOT_TIME,
RUN_LVL,
INIT_PROCESS,
DEAD_PROCESS
};
write_utmpx (types[what], user, id, pid, line);
write_wtmpx (types[what], user, id, pid, line);
}