diff options
-rw-r--r-- | configure.ac | 14 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/pies.h | 11 | ||||
-rw-r--r-- | src/progman.c | 7 | ||||
-rw-r--r-- | src/sysvinit.c | 5 | ||||
-rw-r--r-- | src/utmp.c | 179 |
6 files changed, 214 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac index 0c1d2b9..5a42270 100644 --- a/configure.ac +++ b/configure.ac @@ -32,25 +32,37 @@ AC_PROG_RANLIB AC_PROG_YACC AC_PROG_LEX # Checks for libraries. # Checks for header files. -AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h]) +AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h utmp.h utmpx.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T AC_TYPE_MODE_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SIGNAL IU_CHECK_MEMBERS([struct msghdr.msg_control, struct msghdr.msg_accrights], , , [#include <sys/types.h> #include <sys/socket.h>]) +IU_CHECK_MEMBERS([struct utmp.ut_tv, struct utmp.ut_name, + struct utmp.ut_user, struct utmp.ut_time, + struct utmp.ut_host], , , + [#include <utmp.h>]) + +if test "$ac_cv_header_utmpx_h" = yes; then + IU_CHECK_MEMBERS([struct utmpx.ut_tv, struct utmpx.ut_name, + struct utmpx.ut_user, struct utmpx.ut_time, + struct utmpx.ut_host], , , + [#include <utmpx.h>]) +fi + # Checks for library functions. AC_FUNC_CHOWN AC_FUNC_FORK AC_CHECK_FUNCS([alarm dup2 gethostbyname memmove memset select setenv socket strchr strcspn strtol strtoul sysconf getdtablesize vsyslog]) # Gnulib diff --git a/src/Makefile.am b/src/Makefile.am index 0fca105..3752eae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,12 +29,13 @@ pies_SOURCES = \ meta1lex.l\ pies.c\ progman.c\ socket.c\ sysvinit.c\ url.c\ + utmp.c\ userprivs.c noinst_HEADERS = \ acl.h\ cmdline.h\ meta1gram.h\ @@ -453,9 +453,16 @@ struct inetd_builtin struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); /* sysvinit.c */ void sysvinit_begin (void); int inittrans (void); int is_comp_wait (struct component *comp); - - + +/* utmp.c */ +#define SYSV_ACCT_BOOT 0 +#define SYSV_ACCT_RUNLEVEL 1 +#define SYSV_ACCT_PROC_START 2 +#define SYSV_ACCT_PROC_STOP 3 + +void sysvinit_acct (int what, const char *user, const char *id, pid_t pid, + const char *line); diff --git a/src/progman.c b/src/progman.c index 15b8c44..97216b8 100644 --- a/src/progman.c +++ b/src/progman.c @@ -1389,12 +1389,15 @@ prog_start (struct prog *prog) disable_socket (prog->v.p.socket); } else if (prog->v.p.comp->mode == pies_comp_accept || prog->v.p.comp->mode == pies_comp_inetd || prog->v.p.comp->mode == pies_comp_pass_fd) close (prog->v.p.socket); + else if (is_sysvinit (prog->v.p.comp)) + sysvinit_acct (SYSV_ACCT_PROC_START, "", prog->tag, pid, ""); + prog->pid = pid; prog->v.p.status = status_enabled; debug (1, (_("%s started, pid=%lu"), prog->tag, (unsigned long) pid)); } } @@ -2489,16 +2492,20 @@ progman_cleanup (int expect_term) react (listener, status, pid); if (listener->v.p.comp->flags & CF_WAIT) enable_socket (listener->v.p.socket); } else if (prog->v.p.comp->mode >= pies_mark_sysvinit) { + sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog->tag, pid, ""); prog->v.p.status = status_finished; } else { + if (is_sysvinit (prog->v.p.comp)) + sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog->tag, pid, ""); + prog->v.p.status = status_enabled; prog_stop_dependents (prog); if (!expect_term) react (prog, status, pid); } break; diff --git a/src/sysvinit.c b/src/sysvinit.c index 5a0d98a..ef765a1 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -162,25 +162,30 @@ inittrans () trans = 1; } switch (boot_state) { case sysinit: + break; case boot: + sysvinit_acct (SYSV_ACCT_BOOT, "reboot", "~~", 0, "~"); break; case single0: case single1: newlevel = 'S'; break; case normal: /* boot -> normal */ newlevel = dfl_level ? dfl_level : initdefault; } if (newlevel && newlevel != runlevel) { debug (1, ("RL TRANS: %c -> %c", runlevel, newlevel)); + sysvinit_acct (SYSV_ACCT_RUNLEVEL, "runlevel", "~~", + newlevel + 256 * runlevel, "~"); + mf_proctitle_format ("init [%c]", newlevel); runlevel = newlevel; trans = 1; wait = 0; } if (wait) trans = 1; 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 <http://www.gnu.org/licenses/>. */ + +#include "pies.h" +#include <fcntl.h> +#include <sys/utsname.h> +#include <paths.h> + +#ifdef HAVE_UTMPX_H +# include <utmpx.h> +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 <utmp.h> +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); +} |