/* This file is part of GNU Pies. Copyright (C) 2013-2019 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) { memset (utmp, 0, sizeof (*utmp)); #if defined(HAVE_STRUCT_UTMP_UT_TV) || defined(HAVE_STRUCT_UTMPX_UT_TV) { struct timeval 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) { struct utsname uts; 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); }