From dbce5b355e60fefb84c9d30a08ca534353ab97f7 Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Wed, 17 Sep 2025 23:12:13 +0100 Subject: [PATCH] Add --watchfd option values to an array in the main state, as well as to the currently used variables (#12). --- src/include/options.h | 4 +-- src/include/pv-internal.h | 18 +++++++------ src/include/pv.h | 1 + src/main/main.c | 7 +++++ src/pv/state.c | 55 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/include/options.h b/src/include/options.h index 1dd6a5a..23bbce3 100644 --- a/src/include/options.h +++ b/src/include/options.h @@ -56,8 +56,8 @@ struct opts_s { unsigned int height; /* screen height */ unsigned int argc; /* number of non-option arguments */ unsigned int argv_length; /* allocated array size */ - size_t watchfd_count; /* number of watchfd items */ - size_t watchfd_length; /* allocated array size */ + unsigned int watchfd_count; /* number of watchfd items */ + unsigned int watchfd_length; /* allocated array size */ bool do_nothing; /* exit-without-doing-anything flag */ bool progress; /* progress bar flag */ bool timer; /* timer flag */ diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 2b3259b..ed033db 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -131,13 +131,6 @@ typedef uint16_t pvdisplay_bytecount_t; typedef uint16_t pvdisplay_width_t; #define PVDISPLAY_WIDTH_MAX (65535) /* UINT16_MAX */ -/* Process and (optional) file descriptor to watch with "--watchfd". */ -struct pvwatchspec_s { - pid_t pid; /* process to watch fds of */ - int fd; /* fd to watch, or 0 for all */ -}; -typedef struct pvwatchspec_s *pvwatchspec_t; - /* String pointer, that is the only pointer to this resource, that can be null. */ typedef /*@only@*/ /*@null@*/ char * nullable_string_t; @@ -167,6 +160,15 @@ struct pvstate_s { unsigned int file_count; /* number of input files */ } files; + /********************************* + * Items to watch with --watchfd * + *********************************/ + struct pvwatchspec_s { + /*@only@*/ /*@null@*/ pid_t *pid; /* array of processes to watch fds of */ + /*@only@*/ /*@null@*/ int *fd; /* array of fds to watch in each one (0=all) */ + unsigned int count; /* number of items in these arrays */ + } watchfd; + /******************* * Program control * *******************/ @@ -183,7 +185,7 @@ struct pvstate_s { off_t rate_limit; /* rate limit, in bytes per second */ size_t target_buffer_size; /* buffer size (0=default) */ off_t size; /* total size of data */ - /* TODO: replace watch_pid, watch_fd with an array of structs (#12) */ + /* TODO: replace watch_pid, watch_fd with arrays (#12) */ pid_t watch_pid; /* process to watch fds of */ unsigned int skip_errors; /* skip read errors counter */ int watch_fd; /* fd to watch */ diff --git a/src/include/pv.h b/src/include/pv.h index 208e9b5..5572812 100644 --- a/src/include/pv.h +++ b/src/include/pv.h @@ -240,6 +240,7 @@ extern void pv_state_average_rate_window_set(pvstate_t, unsigned int); extern void pv_state_set_terminal_supports_utf8(pvstate_t, bool); extern void pv_state_inputfiles(pvstate_t, unsigned int, const char **); +extern void pv_state_watchfds(pvstate_t, unsigned int, const pid_t *, const int *); /* * Work out whether we are in the foreground. diff --git a/src/main/main.c b/src/main/main.c index 58f8af2..347dfc9 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -387,6 +387,13 @@ int main(int argc, char **argv) pv_state_inputfiles(state, opts->argc, (const char **) (opts->argv)); } + /* + * Put the list of watchfd items into the PV internal state. + */ + if ((opts->watchfd_count > 0) && (NULL != opts->watchfd_pid) && (NULL != opts->watchfd_fd)) { + pv_state_watchfds(state, opts->watchfd_count, opts->watchfd_pid, opts->watchfd_fd); + } + /* * If stderr is not a terminal and we're neither forcing output nor * outputting numerically, we will have nothing to display at all. diff --git a/src/pv/state.c b/src/pv/state.c index 4f9bef1..3bf8c23 100644 --- a/src/pv/state.c +++ b/src/pv/state.c @@ -323,6 +323,15 @@ void pv_state_free(pvstate_t state) state->files.filename = NULL; } + if (NULL != state->watchfd.pid) { + free(state->watchfd.pid); + state->watchfd.pid = NULL; + } + if (NULL != state->watchfd.fd) { + free(state->watchfd.fd); + state->watchfd.fd = NULL; + } + free(state); return; @@ -703,3 +712,49 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c } state->files.file_count = input_file_count; } + +/* + * Set the arrays of watchfd process IDs and file descriptors. + */ +void pv_state_watchfds(pvstate_t state, unsigned int watchfd_count, const pid_t * pids, const int *fds) +{ + unsigned int item_idx; + /*@only@ */ pid_t *new_pid_array = NULL; + /*@only@ */ int *new_fd_array = NULL; + + /* Free the old arrays, if there were any. */ + if (NULL != state->watchfd.pid) { + free(state->watchfd.pid); + state->watchfd.pid = NULL; + } + if (NULL != state->watchfd.fd) { + free(state->watchfd.fd); + state->watchfd.fd = NULL; + } + state->watchfd.count = 0; + + /* Allocate empty new arrays of the right size. */ + new_pid_array = calloc((size_t) (watchfd_count + 1), sizeof(pid_t)); + if (NULL == new_pid_array) { + /*@-mustfreefresh@ *//* see similar _() issue above */ + pv_error("%s: %s", _("process list allocation failed"), strerror(errno)); + /*@+mustfreefresh@ */ + return; + } + state->watchfd.pid = new_pid_array; + new_fd_array = calloc((size_t) (watchfd_count + 1), sizeof(int)); + if (NULL == new_fd_array) { + /*@-mustfreefresh@ *//* see similar _() issue above */ + pv_error("%s: %s", _("file descriptor list allocation failed"), strerror(errno)); + /*@+mustfreefresh@ */ + return; + } + state->watchfd.fd = new_fd_array; + + /* Populate the new arrays with the values supplied. */ + for (item_idx = 0; item_idx < watchfd_count; item_idx++) { + state->watchfd.pid[item_idx] = pids[item_idx]; + state->watchfd.fd[item_idx] = fds[item_idx]; + } + state->watchfd.count = watchfd_count; +}