aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-01-05 11:56:51 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2013-01-05 11:56:51 +0200
commit4f7c28158308563dcad912d87a0031d095d4690a (patch)
treef8badf11119135268fb58b77e86667b12d0f090c
parentd8221ce9bdd2d7ae6162bed0e1c85e9f7a3ff8f2 (diff)
downloadpies-4f7c28158308563dcad912d87a0031d095d4690a.tar.gz
pies-4f7c28158308563dcad912d87a0031d095d4690a.tar.bz2
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.
-rw-r--r--configure.ac14
-rw-r--r--src/Makefile.am1
-rw-r--r--src/pies.h11
-rw-r--r--src/progman.c7
-rw-r--r--src/sysvinit.c5
-rw-r--r--src/utmp.c179
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\
diff --git a/src/pies.h b/src/pies.h
index fc4f59c..e7ad1c6 100644
--- a/src/pies.h
+++ b/src/pies.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);
+}

Return to:

Send suggestions and report system problems to the System administrator.