diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 6d245ba9..527edb75 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -469,7 +469,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, !(trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { const char *scriptlet_name = is_upgrade ? "pre_upgrade" : "pre_install"; - _alpm_runscriptlet(handle, pkgfile, scriptlet_name, + _alpm_runscriptlet(handle, newpkg->name, pkgfile, scriptlet_name, newpkg->version, oldpkg ? oldpkg->version : NULL, 1); } @@ -641,7 +641,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, char *scriptlet = _alpm_local_db_pkgpath(db, newpkg, "install"); const char *scriptlet_name = is_upgrade ? "post_upgrade" : "post_install"; - _alpm_runscriptlet(handle, scriptlet, scriptlet_name, + _alpm_runscriptlet(handle, newpkg->name, scriptlet, scriptlet_name, newpkg->version, oldpkg ? oldpkg->version : NULL, 0); free(scriptlet); } diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index e7fc7bbf..93edd91a 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -750,6 +750,10 @@ typedef enum _alpm_event_type_t { ALPM_EVENT_LOAD_START, /** Target package is finished loading. */ ALPM_EVENT_LOAD_DONE, + /** An install file is about to be ran */ + ALPM_EVENT_INSTALL_RUN_START, + /** An install file has finished running */ + ALPM_EVENT_INSTALL_RUN_DONE, /** Scriptlet has printed information; See alpm_event_scriptlet_info_t for * arguments. */ ALPM_EVENT_SCRIPTLET_INFO, @@ -840,10 +844,32 @@ typedef struct _alpm_event_optdep_removal_t { alpm_depend_t *optdep; } alpm_event_optdep_removal_t; +/** Enum of the kinds of scriptlets */ +typedef enum _alpm_scriptlet_kind_t { + /** We are running an install file */ + ALPM_SCRIPTLET_KIND_INSTALL_FILE, + /** We are running a hook */ + ALPM_SCRIPTLET_KIND_HOOK, + /** We are running a command */ + ALPM_SCRIPTLET_KIND_COMMAND, +} alpm_scriptlet_kind_t; + +/** We are running an install file. */ +typedef struct _alpm_event_install_run_t { + /** Type of event */ + alpm_event_type_t type; + /** The name of the package */ + const char *pkgname; +} alpm_event_install_run_t; + /** A scriptlet was ran. */ typedef struct _alpm_event_scriptlet_info_t { /** Type of event */ alpm_event_type_t type; + /** The kind of scriptlet being ran */ + alpm_scriptlet_kind_t kind; + /** The name of the scriptlet **/ + const char *name; /** Line of scriptlet output */ const char *line; } alpm_event_scriptlet_info_t; @@ -946,6 +972,8 @@ typedef union _alpm_event_t { alpm_event_package_operation_t package_operation; /** An optdept was remove */ alpm_event_optdep_removal_t optdep_removal; + /** An install file is about to be run */ + alpm_event_install_run_t install_run; /** A scriptlet was ran */ alpm_event_scriptlet_info_t scriptlet_info; /** A database is missing */ diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c index aa25d5f3..702fed66 100644 --- a/lib/libalpm/hook.c +++ b/lib/libalpm/hook.c @@ -522,10 +522,10 @@ static int _alpm_hook_run_hook(alpm_handle_t *handle, struct _alpm_hook_t *hook) alpm_list_count(hook->matches), (alpm_list_fn_cmp)strcmp); /* hooks with multiple triggers could have duplicate matches */ ctx = hook->matches = _alpm_strlist_dedup(hook->matches); - return _alpm_run_chroot(handle, hook->cmd[0], hook->cmd, + return _alpm_run_chroot(handle, hook->name, ALPM_SCRIPTLET_KIND_HOOK, hook->cmd[0], hook->cmd, (_alpm_cb_io) _alpm_hook_feed_targets, &ctx); } else { - return _alpm_run_chroot(handle, hook->cmd[0], hook->cmd, NULL, NULL); + return _alpm_run_chroot(handle, hook->name, ALPM_SCRIPTLET_KIND_HOOK, hook->cmd[0], hook->cmd, NULL, NULL); } } diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index f44eac7f..5a74e8c3 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -694,7 +694,7 @@ int _alpm_remove_single_package(alpm_handle_t *handle, !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, oldpkg, "install"); - _alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0); + _alpm_runscriptlet(handle, oldpkg->name, scriptlet, "pre_remove", pkgver, NULL, 0); free(scriptlet); } } @@ -714,7 +714,7 @@ int _alpm_remove_single_package(alpm_handle_t *handle, !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, oldpkg, "install"); - _alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0); + _alpm_runscriptlet(handle, oldpkg->name, scriptlet, "post_remove", pkgver, NULL, 0); free(scriptlet); } diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 4892820b..f94f8662 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -334,7 +334,7 @@ static int grep(const char *fn, const char *needle) return 0; } -int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath, +int _alpm_runscriptlet(alpm_handle_t *handle, const char *pkgname, const char *filepath, const char *script, const char *ver, const char *oldver, int is_archive) { char arg0[64], arg1[3], cmdline[PATH_MAX]; @@ -407,7 +407,16 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath, _alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\"\n", cmdline); - retval = _alpm_run_chroot(handle, SCRIPTLET_SHELL, argv, NULL, NULL); + alpm_event_install_run_t event = { + .type = ALPM_EVENT_INSTALL_RUN_START, + .pkgname = pkgname, + }; + EVENT(handle, &event); + + retval = _alpm_run_chroot(handle, pkgname, ALPM_SCRIPTLET_KIND_INSTALL_FILE, SCRIPTLET_SHELL, argv, NULL, NULL); + + event.type = ALPM_EVENT_INSTALL_RUN_DONE; + EVENT(handle, &event); cleanup: if(scriptfn && unlink(scriptfn)) { diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 9ee7015e..5f1ebad6 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -49,7 +49,7 @@ typedef struct _alpm_trans_t { void _alpm_trans_free(alpm_trans_t *trans); /* flags is a bitfield of alpm_transflag_t flags */ int _alpm_trans_init(alpm_trans_t *trans, int flags); -int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath, +int _alpm_runscriptlet(alpm_handle_t *handle, const char *name, const char *filepath, const char *script, const char *ver, const char *oldver, int is_archive); #endif /* ALPM_TRANS_H */ diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 83160f00..42ce751e 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -497,18 +497,21 @@ static int _alpm_chroot_write_to_child(alpm_handle_t *handle, int fd, return 0; } -static void _alpm_chroot_process_output(alpm_handle_t *handle, const char *line) +static void _alpm_chroot_process_output(alpm_handle_t *handle, const char *name, + alpm_scriptlet_kind_t kind, const char *line) { alpm_event_scriptlet_info_t event = { .type = ALPM_EVENT_SCRIPTLET_INFO, + .kind = kind, + .name = name, .line = line }; alpm_logaction(handle, "ALPM-SCRIPTLET", "%s", line); EVENT(handle, &event); } -static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, - char *buf, ssize_t *buf_size, ssize_t buf_limit) +static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, const char *name, + alpm_scriptlet_kind_t kind, char *buf, ssize_t *buf_size, ssize_t buf_limit) { ssize_t space = buf_limit - *buf_size - 2; /* reserve 2 for "\n\0" */ ssize_t nread = read(fd, buf + *buf_size, space); @@ -520,7 +523,7 @@ static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, size_t linelen = newline - buf + 1; char old = buf[linelen]; buf[linelen] = '\0'; - _alpm_chroot_process_output(handle, buf); + _alpm_chroot_process_output(handle, name, kind, buf); buf[linelen] = old; *buf_size -= linelen; @@ -530,14 +533,14 @@ static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, } else if(nread == space) { /* we didn't read a full line, but we're out of space */ strcpy(buf + *buf_size, "\n"); - _alpm_chroot_process_output(handle, buf); + _alpm_chroot_process_output(handle, name, kind, buf); *buf_size = 0; } } else if(nread == 0) { /* end-of-file */ if(*buf_size) { strcpy(buf + *buf_size, "\n"); - _alpm_chroot_process_output(handle, buf); + _alpm_chroot_process_output(handle, name, kind, buf); } return -1; } else if(should_retry(errno)) { @@ -546,7 +549,7 @@ static int _alpm_chroot_read_from_child(alpm_handle_t *handle, int fd, /* read error */ if(*buf_size) { strcpy(buf + *buf_size, "\n"); - _alpm_chroot_process_output(handle, buf); + _alpm_chroot_process_output(handle, name, kind, buf); } _alpm_log(handle, ALPM_LOG_ERROR, _("unable to read from pipe (%s)\n"), strerror(errno)); @@ -582,14 +585,16 @@ static void _alpm_reset_signals(void) /** Execute a command with arguments in a chroot. * @param handle the context handle + * @param name a human readable name to describe the command + * @param kind what kind of scriptlet is running * @param cmd command to execute * @param argv arguments to pass to cmd * @param stdin_cb callback to provide input to the chroot on stdin * @param stdin_ctx context to be passed to @a stdin_cb * @return 0 on success, 1 on error */ -int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], - _alpm_cb_io stdin_cb, void *stdin_ctx) +int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kind_t kind, + const char *cmd, char *const argv[], _alpm_cb_io stdin_cb, void *stdin_ctx) { pid_t pid; int child2parent_pipefd[2], parent2child_pipefd[2]; @@ -650,6 +655,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], close(parent2child_pipefd[HEAD]); close(child2parent_pipefd[TAIL]); close(child2parent_pipefd[HEAD]); + if(cwdfd >= 0) { close(cwdfd); } @@ -678,24 +684,38 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], _alpm_handle_free(handle); execv(cmd, argv); /* execv only returns if there was an error */ - fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno)); + fprintf(stderr, _("%s: failed to execv '%s' (%s)\n"), name, cmd, strerror(errno)); exit(1); } else { /* this code runs for the parent only (wait on the child) */ int status; char obuf[PIPE_BUF]; /* writes <= PIPE_BUF are guaranteed atomic */ char ibuf[LINE_MAX]; + char sciptlet_name[32]; ssize_t olen = 0, ilen = 0; nfds_t nfds = 2; struct pollfd fds[2], *child2parent = &(fds[0]), *parent2child = &(fds[1]); int poll_ret; + switch(kind) { + case ALPM_SCRIPTLET_KIND_HOOK: + snprintf(sciptlet_name, 32, "hook '%s'", name); + break; + case ALPM_SCRIPTLET_KIND_INSTALL_FILE: + snprintf(sciptlet_name, 32, "'%s.install'", name); + break; + case ALPM_SCRIPTLET_KIND_COMMAND: + strncpy(sciptlet_name, "ldconfig", 32); + break; + } + child2parent->fd = child2parent_pipefd[TAIL]; child2parent->events = POLLIN; fcntl(child2parent->fd, F_SETFL, O_NONBLOCK); close(child2parent_pipefd[HEAD]); close(parent2child_pipefd[TAIL]); + if(stdin_cb) { parent2child->fd = parent2child_pipefd[HEAD]; parent2child->events = POLLOUT; @@ -718,7 +738,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], } } if(child2parent->revents & POLLIN) { - if(_alpm_chroot_read_from_child(handle, child2parent->fd, + if(_alpm_chroot_read_from_child(handle, child2parent->fd, name, kind, ibuf, &ilen, sizeof(ibuf)) != 0) { /* we encountered end-of-file or an error */ STOP_POLLING(child2parent); @@ -741,7 +761,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], if(ilen) { /* buffer would have already been flushed if it had a newline */ strcpy(ibuf + ilen, "\n"); - _alpm_chroot_process_output(handle, ibuf); + _alpm_chroot_process_output(handle, name, kind, ibuf); } #undef STOP_POLLING @@ -757,7 +777,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], while(waitpid(pid, &status, 0) == -1) { if(errno != EINTR) { - _alpm_log(handle, ALPM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); + _alpm_log(handle, ALPM_LOG_ERROR, _("failed to run %s: call to waitpid failed (%s)\n"), sciptlet_name, strerror(errno)); retval = 1; goto cleanup; } @@ -767,7 +787,8 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], if(WIFEXITED(status)) { _alpm_log(handle, ALPM_LOG_DEBUG, "call to waitpid succeeded\n"); if(WEXITSTATUS(status) != 0) { - _alpm_log(handle, ALPM_LOG_ERROR, _("command failed to execute correctly\n")); + _alpm_log(handle, ALPM_LOG_ERROR, _("%s did not complete sucessfully (%s exited %d)\n"), + sciptlet_name, cmd, WEXITSTATUS(status)); retval = 1; } } else if(WIFSIGNALED(status) != 0) { @@ -776,8 +797,8 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], if(signal_description == NULL) { signal_description = _("Unknown signal"); } - _alpm_log(handle, ALPM_LOG_ERROR, _("command terminated by signal %d: %s\n"), - WTERMSIG(status), signal_description); + _alpm_log(handle, ALPM_LOG_ERROR, _("%s terminated by signal %d: %s\n"), + sciptlet_name, WTERMSIG(status), signal_description); retval = 1; } } @@ -808,10 +829,9 @@ int _alpm_ldconfig(alpm_handle_t *handle) if(access(line, F_OK) == 0) { snprintf(line, PATH_MAX, "%s%s", handle->root, LDCONFIG); if(access(line, X_OK) == 0) { - char arg0[32]; + char *arg0 = strdup(LDCONFIG); char *argv[] = { arg0, NULL }; - strcpy(arg0, "ldconfig"); - return _alpm_run_chroot(handle, LDCONFIG, argv, NULL, NULL); + return _alpm_run_chroot(handle, "ldconfig", ALPM_SCRIPTLET_KIND_COMMAND, LDCONFIG, argv, NULL, NULL); } } diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 9877edec..f3f267be 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -129,8 +129,8 @@ ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, int fu typedef ssize_t (*_alpm_cb_io)(void *buf, ssize_t len, void *ctx); -int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], - _alpm_cb_io in_cb, void *in_ctx); +int _alpm_run_chroot(alpm_handle_t *handle, const char *name, alpm_scriptlet_kind_t kind, + const char *cmd, char *const argv[], _alpm_cb_io in_cb, void *in_ctx); int _alpm_ldconfig(alpm_handle_t *handle); int _alpm_str_cmp(const void *s1, const void *s2); char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename); diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 27a18a4f..c8e6752d 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -217,7 +217,10 @@ static int number_length(size_t n) /* callback to handle messages/notifications from libalpm transactions */ void cb_event(void *ctx, alpm_event_t *event) { + static int install_line_count = 0; + const colstr_t *colstr = &config->colstr; (void)ctx; + if(config->print) { console_cursor_move_end(); return; @@ -313,8 +316,16 @@ void cb_event(void *ctx, alpm_event_t *event) printf(_("loading package files...\n")); } break; + case ALPM_EVENT_INSTALL_RUN_START: + install_line_count = 0; + break; case ALPM_EVENT_SCRIPTLET_INFO: - fputs(event->scriptlet_info.line, stdout); + /* onlt say we're running the install file if it outputs */ + if(install_line_count == 0 && event->scriptlet_info.kind == ALPM_SCRIPTLET_KIND_INSTALL_FILE) { + printf("Running %s.install...\n", event->scriptlet_info.name); + } + install_line_count++; + printf(" %s%s%s", colstr->scriptlet, event->scriptlet_info.line, colstr->nocolor); break; case ALPM_EVENT_DB_RETRIEVE_START: on_progress = 1; @@ -413,6 +424,7 @@ void cb_event(void *ctx, alpm_event_t *event) case ALPM_EVENT_DISKSPACE_DONE: case ALPM_EVENT_HOOK_DONE: case ALPM_EVENT_HOOK_RUN_DONE: + case ALPM_EVENT_INSTALL_RUN_DONE: /* nothing */ break; } diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 7318ad54..91a49577 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -63,6 +63,7 @@ config_t *config = NULL; #define BOLDMAGENTA "\033[1;35m" #define BOLDCYAN "\033[1;36m" #define BOLDWHITE "\033[1;37m" +#define BLUE117 "\033[38;5;117m" #define GREY46 "\033[38;5;243m" void enable_colors(int colors) @@ -70,27 +71,29 @@ void enable_colors(int colors) colstr_t *colstr = &config->colstr; if(colors == PM_COLOR_ON) { - colstr->colon = BOLDBLUE "::" BOLD " "; - colstr->title = BOLD; - colstr->repo = BOLDMAGENTA; - colstr->version = BOLDGREEN; - colstr->groups = BOLDBLUE; - colstr->meta = BOLDCYAN; - colstr->warn = BOLDYELLOW; - colstr->err = BOLDRED; - colstr->faint = GREY46; - colstr->nocolor = NOCOLOR; + colstr->colon = BOLDBLUE "::" BOLD " "; + colstr->title = BOLD; + colstr->repo = BOLDMAGENTA; + colstr->version = BOLDGREEN; + colstr->groups = BOLDBLUE; + colstr->meta = BOLDCYAN; + colstr->warn = BOLDYELLOW; + colstr->err = BOLDRED; + colstr->scriptlet = BLUE117; + colstr->faint = GREY46; + colstr->nocolor = NOCOLOR; } else { - colstr->colon = ":: "; - colstr->title = ""; - colstr->repo = ""; - colstr->version = ""; - colstr->groups = ""; - colstr->meta = ""; - colstr->warn = ""; - colstr->err = ""; - colstr->faint = ""; - colstr->nocolor = ""; + colstr->colon = ":: "; + colstr->title = ""; + colstr->repo = ""; + colstr->version = ""; + colstr->groups = ""; + colstr->meta = ""; + colstr->warn = ""; + colstr->err = ""; + colstr->scriptlet = ""; + colstr->faint = ""; + colstr->nocolor = ""; } } diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 3fb07425..a4784724 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -32,6 +32,7 @@ typedef struct __colstr_t { const char *warn; const char *err; const char *faint; + const char *scriptlet; const char *nocolor; } colstr_t;