Record all old-style formatting options, and the full string for the extra display spec, in the control structure; make pv_remote_set only use internal pv state structures so it can be part of the internal pv library where it belongs, and not need to know about main()'s options array.
This commit is contained in:
@@ -31,6 +31,7 @@ typedef enum {
|
||||
PV_ACTION_TRANSFER, /* transfer data */
|
||||
PV_ACTION_STORE_AND_FORWARD, /* store to file, then output from it */
|
||||
PV_ACTION_WATCHFD, /* watch process file descriptors */
|
||||
PV_ACTION_REMOTE_CONTROL, /* remotely control another pv */
|
||||
PV_ACTION_QUERY /* watch the state of another pv */
|
||||
} pvaction_t;
|
||||
|
||||
|
||||
@@ -179,7 +179,8 @@ struct pvstate_s {
|
||||
double delay_start; /* delay before first display */
|
||||
/*@only@*/ /*@null@*/ char *name; /* display name */
|
||||
/*@only@*/ /*@null@*/ char *format_string; /* output format string */
|
||||
/*@only@*/ /*@null@*/ char *extra_format_string; /* extra format string */
|
||||
/*@only@*/ /*@null@*/ char *extra_display_spec; /* full spec for extra displays */
|
||||
/*@only@*/ /*@null@*/ char *extra_format_string; /* extra format string alone */
|
||||
/*@null@*/ char *output_name; /* name of the output, for diagnostics */
|
||||
/*@null@*/ char *default_bar_style; /* which bar style to use by default */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
@@ -193,6 +194,17 @@ struct pvstate_s {
|
||||
pvdisplay_width_t width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
unsigned int extra_displays; /* bitmask of extra display destinations */
|
||||
struct { /* old-style format options (used by -R) */
|
||||
size_t lastwritten; /* --last-written (amount) */
|
||||
bool progress; /* --progress */
|
||||
bool timer; /* --timer */
|
||||
bool eta; /* --eta */
|
||||
bool fineta; /* --fineta */
|
||||
bool rate; /* --rate */
|
||||
bool average_rate; /* --average-rate */
|
||||
bool bytes; /* --bytes */
|
||||
bool bufpercent; /* --buffer-percent */
|
||||
} format_option;
|
||||
bool force; /* display even if not on terminal */
|
||||
bool cursor; /* use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
|
||||
@@ -297,6 +297,19 @@ extern int pv_watchfd_loop(pvstate_t);
|
||||
*/
|
||||
extern int pv_query_loop(pvstate_t, pid_t);
|
||||
|
||||
/*
|
||||
* Set the options of another pv process.
|
||||
*/
|
||||
int pv_remote_set(pvstate_t, pid_t);
|
||||
|
||||
/*
|
||||
* Query another pv process for its elapsed transfer time, amount
|
||||
* transferred, and total size, and update the local state with those
|
||||
* values. Optionally also return the total size separately. Reports
|
||||
* errors unless "silent" is true.
|
||||
*/
|
||||
int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_t *sizeptr, bool silent);
|
||||
|
||||
/*
|
||||
* Shut down signal handlers after running the main loop.
|
||||
*/
|
||||
|
||||
+5
-21
@@ -23,9 +23,6 @@
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
int pv_remote_set(opts_t, pvstate_t);
|
||||
int pv_remote_transferstate_fetch(pvstate_t, pid_t, /*@null@ */ off_t *, bool);
|
||||
|
||||
/*
|
||||
* Write a PID file, returning nonzero on error. Write it atomically, such
|
||||
* that the file either exists and contains the PID, or is not updated at
|
||||
@@ -337,23 +334,6 @@ int main(int argc, char **argv)
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
/*
|
||||
* -R specified - send the message, then exit.
|
||||
*/
|
||||
if (opts->remote > 0) {
|
||||
/* Initialise signal handling. */
|
||||
pv_sig_init(state);
|
||||
/* Send the message. */
|
||||
retcode = pv_remote_set(opts, state);
|
||||
/* Close down the signal handling. */
|
||||
pv_sig_fini(state);
|
||||
/* Free resources. */
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
/* Early exit. */
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a PID file if -P was specified.
|
||||
*/
|
||||
@@ -572,8 +552,12 @@ int main(int argc, char **argv)
|
||||
/* "Watch file descriptor(s) of another process" mode. */
|
||||
retcode = pv_watchfd_loop(state);
|
||||
break;
|
||||
case PV_ACTION_REMOTE_CONTROL:
|
||||
/* Change the options of another running pv. */
|
||||
retcode = pv_remote_set(state, opts->remote);
|
||||
break;
|
||||
case PV_ACTION_QUERY:
|
||||
/* "Watch progress of another pv" mode. */
|
||||
/* Query the progress of another running pv. */
|
||||
retcode = pv_query_loop(state, opts->query);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -996,6 +996,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
break;
|
||||
case 'R':
|
||||
opts->remote = (pid_t) pv_getnum_count(optarg, false);
|
||||
opts->action = PV_ACTION_REMOTE_CONTROL;
|
||||
break;
|
||||
case 'Q':
|
||||
opts->query = (pid_t) pv_getnum_count(optarg, false);
|
||||
|
||||
+47
-50
@@ -9,7 +9,6 @@
|
||||
/* TODO: move this to srv/pv/ instead of src/main/ since it uses internal pv structures. */
|
||||
|
||||
#include "config.h"
|
||||
#include "options.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
@@ -24,8 +23,6 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void pv_error(char *, ...);
|
||||
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
|
||||
/* Structure for transferring settings with --remote. */
|
||||
@@ -74,7 +71,7 @@ struct query_msg {
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
*/
|
||||
int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
{
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
@@ -92,59 +89,59 @@ int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
/*
|
||||
* Check that the remote process exists.
|
||||
*/
|
||||
if (kill((pid_t) (opts->remote), 0) != 0) {
|
||||
pv_error("%u: %s", opts->remote, strerror(errno));
|
||||
if (kill((pid_t) (remote), 0) != 0) {
|
||||
pv_error("%u: %s", remote, strerror(errno));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure parameters are within sensible bounds.
|
||||
*/
|
||||
if (opts->width < 1)
|
||||
opts->width = 80;
|
||||
if (opts->height < 1)
|
||||
opts->height = 25;
|
||||
if (opts->width > 999999)
|
||||
opts->width = 999999;
|
||||
if (opts->height > 999999)
|
||||
opts->height = 999999;
|
||||
if ((opts->interval > 0) && (opts->interval < 0.1))
|
||||
opts->interval = 0.1;
|
||||
if (opts->interval > 600)
|
||||
opts->interval = 600;
|
||||
|
||||
/*
|
||||
* Copy parameters into message buffer.
|
||||
*/
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
msgbuf.progress = opts->progress;
|
||||
msgbuf.timer = opts->timer;
|
||||
msgbuf.eta = opts->eta;
|
||||
msgbuf.fineta = opts->fineta;
|
||||
msgbuf.rate = opts->rate;
|
||||
msgbuf.average_rate = opts->average_rate;
|
||||
msgbuf.bytes = opts->bytes;
|
||||
msgbuf.bufpercent = opts->bufpercent;
|
||||
msgbuf.lastwritten = opts->lastwritten;
|
||||
msgbuf.rate_limit = opts->rate_limit;
|
||||
msgbuf.buffer_size = opts->buffer_size;
|
||||
msgbuf.size = opts->size;
|
||||
msgbuf.interval = opts->interval;
|
||||
msgbuf.width = opts->width;
|
||||
msgbuf.height = opts->height;
|
||||
msgbuf.width_set_manually = opts->width_set_manually;
|
||||
msgbuf.height_set_manually = opts->height_set_manually;
|
||||
msgbuf.progress = state->control.format_option.progress;
|
||||
msgbuf.timer = state->control.format_option.timer;
|
||||
msgbuf.eta = state->control.format_option.eta;
|
||||
msgbuf.fineta = state->control.format_option.fineta;
|
||||
msgbuf.rate = state->control.format_option.rate;
|
||||
msgbuf.average_rate = state->control.format_option.average_rate;
|
||||
msgbuf.bytes = state->control.format_option.bytes;
|
||||
msgbuf.bufpercent = state->control.format_option.bufpercent;
|
||||
msgbuf.lastwritten = state->control.format_option.lastwritten;
|
||||
msgbuf.rate_limit = state->control.rate_limit;
|
||||
msgbuf.buffer_size = state->control.target_buffer_size;
|
||||
msgbuf.size = state->control.size;
|
||||
msgbuf.interval = state->control.interval;
|
||||
msgbuf.width = (unsigned int) (state->control.width);
|
||||
msgbuf.height = (unsigned int) (state->control.height);
|
||||
msgbuf.width_set_manually = state->control.width_set_manually;
|
||||
msgbuf.height_set_manually = state->control.height_set_manually;
|
||||
|
||||
if (opts->name != NULL) {
|
||||
strncpy(msgbuf.name, opts->name, sizeof(msgbuf.name) - 1); /* flawfinder: ignore */
|
||||
if (state->control.name != NULL) {
|
||||
strncpy(msgbuf.name, state->control.name, sizeof(msgbuf.name) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (opts->format != NULL) {
|
||||
strncpy(msgbuf.format, opts->format, sizeof(msgbuf.format) - 1); /* flawfinder: ignore */
|
||||
if (state->control.format_string != NULL) {
|
||||
strncpy(msgbuf.format, state->control.format_string, sizeof(msgbuf.format) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (opts->extra_display != NULL) {
|
||||
strncpy(msgbuf.extra_display, opts->extra_display, sizeof(msgbuf.extra_display) - 1); /* flawfinder: ignore */
|
||||
if (state->control.extra_display_spec != NULL) {
|
||||
strncpy(msgbuf.extra_display, state->control.extra_display_spec, sizeof(msgbuf.extra_display) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure parameters are within sensible bounds.
|
||||
*/
|
||||
if (msgbuf.width < 1)
|
||||
msgbuf.width = 80;
|
||||
if (msgbuf.height < 1)
|
||||
msgbuf.height = 25;
|
||||
if (msgbuf.width > 999999)
|
||||
msgbuf.width = 999999;
|
||||
if (msgbuf.height > 999999)
|
||||
msgbuf.height = 999999;
|
||||
if ((msgbuf.interval > 0) && (msgbuf.interval < 0.1))
|
||||
msgbuf.interval = 0.1;
|
||||
if (msgbuf.interval > 600)
|
||||
msgbuf.interval = 600;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: name, format, and extra_display are
|
||||
* explicitly bounded to 1 less than the size of their buffer and
|
||||
@@ -184,8 +181,8 @@ int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
*/
|
||||
signal_sender = 0;
|
||||
(void) pv_sigusr2_received(state, &signal_sender);
|
||||
if (kill((pid_t) (opts->remote), SIGUSR2) != 0) {
|
||||
pv_error("%u: %s", opts->remote, strerror(errno));
|
||||
if (kill((pid_t) (remote), SIGUSR2) != 0) {
|
||||
pv_error("%u: %s", remote, strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
@@ -212,7 +209,7 @@ int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
timeout -= 10000;
|
||||
|
||||
if (pv_sigusr2_received(state, &signal_sender)) {
|
||||
if (signal_sender == opts->remote) {
|
||||
if (signal_sender == remote) {
|
||||
debug("%s", "message received");
|
||||
received = true;
|
||||
}
|
||||
@@ -239,7 +236,7 @@ int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
*/
|
||||
pv_error("%u: %s", opts->remote, _("message not received"));
|
||||
pv_error("%u: %s", remote, _("message not received"));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
/*@+mustfreefresh @ */
|
||||
}
|
||||
@@ -643,7 +640,7 @@ void pv_remote_check( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
|
||||
|
||||
int pv_remote_set( /*@unused@ */
|
||||
__attribute__((unused)) opts_t opts, /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
__attribute__((unused)) pvstate_t state, /*@unused@ */ __attribute__((unused)) pid_t remote)
|
||||
{
|
||||
/*@-mustfreefresh@ *//* splint - see above */
|
||||
pv_error("%s", _("SA_SIGINFO not supported on this system"));
|
||||
|
||||
@@ -336,6 +336,11 @@ void pv_state_free(pvstate_t state)
|
||||
state->control.format_string = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->control.extra_display_spec) {
|
||||
free(state->control.extra_display_spec);
|
||||
state->control.extra_display_spec = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->control.extra_format_string) {
|
||||
free(state->control.extra_format_string);
|
||||
state->control.extra_format_string = NULL;
|
||||
@@ -384,6 +389,16 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b
|
||||
(void) pv_strlcat(state->control.default_format, y, sizeof(state->control.default_format)); \
|
||||
}
|
||||
|
||||
state->control.format_option.progress = progress;
|
||||
state->control.format_option.timer = timer;
|
||||
state->control.format_option.eta = eta;
|
||||
state->control.format_option.fineta = fineta;
|
||||
state->control.format_option.rate = rate;
|
||||
state->control.format_option.average_rate = average_rate;
|
||||
state->control.format_option.bytes = bytes;
|
||||
state->control.format_option.bufpercent = bufpercent;
|
||||
state->control.format_option.lastwritten = lastwritten;
|
||||
|
||||
state->control.default_format[0] = '\0';
|
||||
|
||||
if (false == state->control.numeric) {
|
||||
@@ -612,6 +627,11 @@ void pv_state_extra_display_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
const char *word_start;
|
||||
size_t offset;
|
||||
|
||||
if (NULL != state->control.extra_display_spec) {
|
||||
free(state->control.extra_display_spec);
|
||||
state->control.extra_display_spec = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->control.extra_format_string) {
|
||||
free(state->control.extra_format_string);
|
||||
state->control.extra_format_string = NULL;
|
||||
@@ -621,6 +641,9 @@ void pv_state_extra_display_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
if (NULL == val)
|
||||
return;
|
||||
|
||||
if (NULL != val)
|
||||
state->control.extra_display_spec = pv_strdup(val);
|
||||
|
||||
word_start = val;
|
||||
while (NULL != word_start && '\0' != word_start[0]) {
|
||||
offset = 0;
|
||||
|
||||
Reference in New Issue
Block a user