From 4f7c28158308563dcad912d87a0031d095d4690a Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 5 Jan 2013 11:56:51 +0200 Subject: Write utmp/wtmp records in sysvinit mode. * configure.ac: Check for utmp.h, utmpx.h * src/utmp.c: New file. * src/Makefile.am: Add utmp.c * src/pies.h (sysvinit_acct): New proto. * src/progman.c (prog_start, progman_cleanup): Call sysvinit_acct. * src/sysvinit.c (inittrans): Call sysvinit_acct. Set proctitle. --- src/utmp.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 src/utmp.c (limited to 'src/utmp.c') diff --git a/src/utmp.c b/src/utmp.c new file mode 100644 index 0000000..d4452bc --- /dev/null +++ b/src/utmp.c @@ -0,0 +1,179 @@ +/* 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; + write (fd, ut, sizeof (*ut)); + 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 +} + + +int wtmpxreboot = 0; + +void +write_wtmpx (int type, const char *user, const char *id, pid_t pid, + const char *line) +{ + UTMPX utmp; + + if (access (WTMP_FILE, W_OK)) + { + logmsg (LOG_NOTICE, _("cannot open %s for writing"), WTMP_FILE); + 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); +} + +int utmpreboot = 0; + +void +write_utmpx (int type, const char *user, const char *id, pid_t pid, + const char *line) +{ + UTMPX utmp; + + if (access (UTMP_FILE, W_OK)) + { + logmsg (LOG_NOTICE, _("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); +} -- cgit v1.2.1