/* hooks.c:
*
****************************************************************
* Copyright (C) 2003 Tom Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/bugs/panic.h"
#include "hackerlab/os/stdarg.h"
#include "hackerlab/os/sys/types.h"
#include "hackerlab/os/unistd.h"
#include "hackerlab/os/sys/wait.h"
#include "hackerlab/os/signal.h"
#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/arrays/ar.h"
#include "hackerlab/vu/safe.h"
#include "libarch/my.h"
#include "libarch/hooks.h"
extern char ** environ;
int
arch_run_hook (t_uchar const * const name, ...)
{
t_uchar * hook_script = 0;
int exit_status = 0;
hook_script = arch_my_hook_script ();
if (hook_script)
{
va_list ap;
t_uchar * hook_tail = 0;
t_uchar ** argv = 0;
t_uchar ** env = 0;
int x;
int pid;
hook_tail = file_name_tail (0, hook_script);
ar_push_uchar_star (&argv, str_save (0, hook_tail));
ar_push_uchar_star (&argv, str_save (0, name));
ar_push_uchar_star (&argv, 0);
va_start (ap, name);
while (1)
{
t_uchar * var;
t_uchar * val;
var = va_arg (ap, t_uchar *);
if (!var)
break;
val = va_arg (ap, t_uchar *);
invariant (!!val);
ar_push_uchar_star (&env, str_alloc_cat_many (0, var, "=", val, str_end));
}
va_end (ap);
for (x = 0; environ[x]; ++x)
ar_push_uchar_star (&env, str_save (0, environ[x]));
ar_push_uchar_star (&env, 0);
pid = fork ();
if (pid == -1)
panic ("unable to fork for hook");
if (pid)
{
int status;
int wait_pid;
wait_pid = waitpid (pid, &status, 0);
if (wait_pid < 0)
{
panic_msg ("error waiting for hook subprocess");
kill (0, SIGKILL);
panic ("error waiting for hook subprocess");
}
if (WIFSIGNALED (status))
{
safe_printfmt (2, "\n");
safe_printfmt (2, "arch_run_hook: hook subprocess killed by signal %d\n", WTERMSIG (status));
safe_printfmt (2, "\n");
exit (2);
return -1;
}
else if (!WIFEXITED (status))
{
panic_msg ("waitpid returned for a non-exited hook process");
kill (0, SIGKILL);
panic ("waitpid returned for a non-exited hook process and kill failed");
return -1;
}
else
{
exit_status = WEXITSTATUS (status);
}
}
else
{
execve (hook_script, (char **)argv, (char **)env);
panic ("invoke_tar_extract: execve for hook script returned to caller");
exit (2);
}
lim_free (0, hook_tail);
for (x = 0; x < ar_size_uchar_star (argv); ++x)
{
lim_free (0, argv[x]);
}
ar_free_uchar_star (&argv);
for (x = 0; x < ar_size_uchar_star (env); ++x)
{
lim_free (0, env[x]);
}
ar_free_uchar_star (&env);
}
lim_free (0, hook_script);
return exit_status;
}
/* tag: Tom Lord Mon Jun 16 17:47:47 2003 (hooks.c)
*/
syntax highlighted by Code2HTML, v. 0.9.1