=== modified file 'init/cfgfile.c' --- old/init/cfgfile.c 2007-03-13 18:39:13 +0000 +++ new/init/cfgfile.c 2009-05-20 14:23:50 +0000 @@ -151,6 +151,9 @@ static int cfg_stanza_chdir (Job *job, NihConfigStanza *stanza, const char *file, size_t len, size_t *pos, size_t *lineno); +static int cfg_stanza_utmp (Job *job, NihConfigStanza *stanza, + const char *file, size_t len, + size_t *pos, size_t *lineno); static char *cfg_job_name (const void *parent, const char *prefix, const char *dirname, const char *path) @@ -199,6 +202,7 @@ { "limit", (NihConfigHandler)cfg_stanza_limit }, { "chroot", (NihConfigHandler)cfg_stanza_chroot }, { "chdir", (NihConfigHandler)cfg_stanza_chdir }, + { "utmp", (NihConfigHandler)cfg_stanza_utmp }, NIH_CONFIG_LAST }; @@ -1711,6 +1715,41 @@ return nih_config_skip_comment (file, len, pos, lineno); } +/** + * cfg_stanza_utmp: + * @job: job being parsed, + * @stanza: stanza found, + * @file: file or string to parse, + * @len: length of @file, + * @pos: offset within @file, + * @lineno: line number. + * + * Parse an utmp stanza from @file, extracting a single argument + * containing a terminal name suffix. + * + * Returns: zero on success, negative value on error. + **/ +static int +cfg_stanza_utmp (Job *job, + NihConfigStanza *stanza, + const char *file, + size_t len, + size_t *pos, + size_t *lineno) +{ + nih_assert (job != NULL); + nih_assert (stanza != NULL); + nih_assert (file != NULL); + nih_assert (pos != NULL); + + if (job->utmp) + nih_return_error (-1, CFG_DUPLICATE_VALUE, + _(CFG_DUPLICATE_VALUE_STR)); + + job->utmp = nih_config_next_arg (job, file, len, pos, lineno); + + return nih_config_skip_comment (file, len, pos, lineno); +} /** * cfg_read_job: === modified file 'init/job.c' --- old/init/job.c 2007-10-11 21:20:32 +0000 +++ new/init/job.c 2009-05-20 14:25:02 +0000 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -352,6 +353,8 @@ job->chroot = NULL; job->chdir = NULL; + job->utmp = NULL; + nih_hash_add (jobs, &job->entry); return job; @@ -519,6 +522,12 @@ goto error; } + if (old_job->utmp) { + job->utmp = nih_strdup (job, old_job->utmp); + if (! job->utmp) + goto error; + } + return job; error: @@ -1692,6 +1701,58 @@ job->kill_timer = NULL; } + /* clean utmp before clean pid */ + if (job->utmp) { + /* clean utmp entry as described in utmp man page */ + struct utmp utmp; + struct utmp *utmptr; + + /* from sysvinit init.c */ + + /* clean out an utmp struct. */ + memset(&utmp, 0, sizeof(utmp)); + + /* set ut_id from utmp stanza */ + strncpy(utmp.ut_id, job->utmp, sizeof(utmp.ut_id)); + utmp.ut_pid = job->process[process]->pid; + utmp.ut_type = USER_PROCESS; + + /* Find existing entry for the tty line. */ + setutent(); + while ((utmptr = getutid(&utmp)) != NULL) { + if (utmptr->ut_pid == job->process[process]->pid) { + struct timeval tv; + + /* set type and clean ut_user, ut_host, ut_time as described in utmp(5) */ + utmptr->ut_type = DEAD_PROCESS; + memset(utmptr->ut_user, 0, UT_NAMESIZE); + memset(utmptr->ut_host, 0, UT_HOSTSIZE); + utmptr->ut_time = 0; + /* Update existing utmp file. */ + setutent(); + pututline(utmptr); + + /* set ut_time for log */ +#if defined(__GLIBC__) + gettimeofday(&tv, NULL); + utmptr->ut_tv.tv_sec = tv.tv_sec; + utmptr->ut_tv.tv_usec = tv.tv_usec; +#else + time(&utmptr->ut_time); +#endif + /* Write wtmp entry */ + updwtmp (WTMP, utmptr); + + break; + } + } + endutent(); + + /* end of sysvinit code */ + + } + + /* Clear the process pid field */ job->process[process]->pid = 0; === modified file 'init/job.h' --- old/init/job.h 2007-03-13 17:20:20 +0000 +++ new/init/job.h 2009-05-20 14:25:25 +0000 @@ -143,6 +143,7 @@ * @limits: resource limits indexed by resource, * @chroot: root directory of process (implies @chdir if not set), * @chdir: working directory of process, + * @utmp: terminal name suffix or inittab ID, * * This structure represents a known task or service that should be tracked * by the init daemon; as tasks and services are fundamentally identical, @@ -208,6 +209,7 @@ struct rlimit *limits[RLIMIT_NLIMITS]; char *chroot; char *chdir; + char *utmp; }; === modified file 'init/paths.h' --- old/init/paths.h 2007-02-06 15:51:19 +0000 +++ new/init/paths.h 2009-05-20 14:25:48 +0000 @@ -91,5 +91,13 @@ #define TELINIT "/sbin/telinit" #endif +/** + * WTMP + * + * This is wtmp log file. + **/ +#ifndef WTMP +#define WTMP "/var/log/wtmp" +#endif #endif /* INIT_PATHS_H */ === modified file 'init/process.c' --- old/init/process.c 2007-10-11 21:08:38 +0000 +++ new/init/process.c 2009-05-20 14:33:06 +0000 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,7 @@ /* Prototypes for static functions */ static int process_setup_limits (Job *job); static int process_setup_environment (Job *job); +static int process_utmp (Job *job, int type); /** @@ -149,6 +151,11 @@ if (process_setup_environment (job) < 0) goto error; + /* And set INIT_PROCESS for utmp entry */ + if (process_utmp(job, INIT_PROCESS) < 0) { + goto error; + } + /* Execute the process, if we escape from here it failed */ if (execvp (argv[0], argv) < 0) nih_error_raise_system (); @@ -270,6 +277,52 @@ return 0; } +/** + * process_utmp: + * @job: job details. + * + * Write utmp entry based on the details in @job. + * + * Returns: zero on success, negative value on raised error. + **/ +static int +process_utmp (Job *job, int type) +{ + + nih_assert (job != NULL); + + /* set INIT_PROCESS when utmp stanza is set */ + if (job->utmp) { + struct utmp utmp; + struct timeval tv; + + /* clean out an utmp struct. */ + memset(&utmp, 0, sizeof(utmp)); + + /* set ut_id from utmp stanza */ + strncpy(utmp.ut_id, job->utmp, sizeof(utmp.ut_id)); + utmp.ut_pid = getpid(); + utmp.ut_type = type; + +#if defined(__GLIBC__) + gettimeofday(&tv, NULL); + utmp.ut_tv.tv_sec = tv.tv_sec; + utmp.ut_tv.tv_usec = tv.tv_usec; +#else + time(&utmp.ut_time); +#endif + + /* Find existing entry for the tty line. */ + setutent(); + pututline(&utmp); + endutent(); + + /* Write wtmp entry */ + updwtmp (WTMP, &utmp); + } + return 0; +} + /** * process_kill: === modified file 'init/tests/test_job.c' --- old/init/tests/test_job.c 2007-10-11 21:20:32 +0000 +++ new/init/tests/test_job.c 2009-05-20 14:33:55 +0000 @@ -225,6 +225,8 @@ TEST_EQ_P (job->chroot, NULL); TEST_EQ_P (job->chdir, NULL); + TEST_EQ_P (job->utmp, NULL); + nih_list_free (&job->entry); } } @@ -320,6 +322,8 @@ TEST_EQ_P (copy->chroot, NULL); TEST_EQ_P (copy->chdir, NULL); + TEST_EQ_P (copy->utmp, NULL); + nih_list_free (©->entry); } @@ -436,6 +440,8 @@ job->chroot = nih_strdup (job, "/var/run/daemon"); job->chdir = nih_strdup (job, "/etc"); + job->utmp = nih_strdup (job, "1"); + TEST_ALLOC_FAIL { copy = job_copy (NULL, job); @@ -588,6 +594,8 @@ TEST_EQ_STR (copy->chroot, job->chroot); TEST_ALLOC_PARENT (copy->chdir, copy); TEST_EQ_STR (copy->chdir, job->chdir); + TEST_ALLOC_PARENT (copy->utmp, copy); + TEST_EQ_STR (copy->utmp, job->utmp); nih_list_free (©->entry); }