/* 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) */