diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 5c8e565..b1b39ce 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -25,7 +25,7 @@ extern "C" { #define RATE_GRANULARITY 100000000 /* nsec between -L rate chunks */ #define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */ -#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R */ +#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R and -Q */ #define BUFFER_SIZE (size_t) 409600 /* default transfer buffer size */ #define BUFFER_SIZE_MAX (size_t) 524288 /* max auto transfer buffer size */ #define MAX_READ_AT_ONCE (size_t) 524288 /* max to read() in one go */ @@ -230,6 +230,9 @@ struct pvstate_s { struct sigaction old_sigterm; #ifdef PV_REMOTE_CONTROL struct sigaction old_sigusr2; +#endif +#ifdef PV_REMOTE_QUERY + struct sigaction old_sigusr1; #endif struct sigaction old_sigalrm; struct timespec tstp_time; /* see pv_sig_tstp() / __cont() */ @@ -237,6 +240,10 @@ struct pvstate_s { #ifdef PV_REMOTE_CONTROL volatile sig_atomic_t rxusr2; /* whether SIGUSR2 was received */ volatile pid_t sender_usr2; /* PID of sending process for SIGUSR2 */ +#endif +#ifdef PV_REMOTE_QUERY + volatile sig_atomic_t rxusr1; /* whether SIGUSR1 was received */ + volatile pid_t sender_usr1; /* PID of sending process for SIGUSR1 */ #endif } signal; @@ -620,9 +627,7 @@ void pv_sig_allowpause(void); void pv_sig_checkbg(void); void pv_sig_nopause(void); -void pv_remote_init(pvstate_t); bool pv_remote_check(pvstate_t); -void pv_remote_fini(pvstate_t); int pv_remote_set(pvstate_t); int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool); diff --git a/src/main/main.c b/src/main/main.c index 437ea85..0f64d29 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -24,10 +24,7 @@ #endif int pv_remote_set(opts_t, pvstate_t); -void pv_remote_init(void); -void pv_remote_fini(void); -// TODO -// int pv_remote_transferstate_fetch(pvstate_t, pid_t, /*@null@ */ off_t *); +int pv_remote_transferstate_fetch(pvstate_t, pid_t, /*@null@ */ off_t *); /* * Write a PID file, returning nonzero on error. Write it atomically, such @@ -503,7 +500,7 @@ int main(int argc, char **argv) */ if (PV_ACTION_QUERY == opts->action) { opts->size = 0; -// TODO retcode = pv_remote_transferstate_fetch(state, opts->query, &(opts->size)); + retcode = pv_remote_transferstate_fetch(state, opts->query, &(opts->size)); if (0 != retcode) { pv_sig_fini(state); pv_state_free(state); @@ -565,15 +562,11 @@ int main(int argc, char **argv) break; case PV_ACTION_TRANSFER: /* Normal "transfer data" mode. */ - pv_remote_init(); retcode = pv_main_loop(state); - pv_remote_fini(); break; case PV_ACTION_STORE_AND_FORWARD: /* Store-and-forward transfer mode. */ - pv_remote_init(); retcode = pv__store_and_forward(state, opts, can_have_eta); - pv_remote_fini(); break; case PV_ACTION_WATCHFD: /* "Watch file descriptor(s) of another process" mode. */ @@ -581,9 +574,7 @@ int main(int argc, char **argv) break; case PV_ACTION_QUERY: /* "Watch progress of another pv" mode. */ - pv_remote_init(); /* TODO: loop watching transfer progress until finished. */ - pv_remote_fini(); break; } diff --git a/src/main/remote.c b/src/main/remote.c index c52f2e5..90a7330 100644 --- a/src/main/remote.c +++ b/src/main/remote.c @@ -21,9 +21,10 @@ #include #include -#ifdef PV_REMOTE_CONTROL void pv_error(char *, ...); +#ifdef PV_REMOTE_CONTROL + struct remote_msg { bool progress; /* progress bar flag */ bool timer; /* timer flag */ @@ -324,40 +325,51 @@ bool pv_remote_check(pvstate_t state) } -/* - * Initialise remote message reception handling. - */ -void pv_remote_init(void) -{ -} - - -/* - * Clean up after remote message reception handling. - */ -void pv_remote_fini(void) -{ -} - #else /* !PV_REMOTE_CONTROL */ /* * Dummy stubs for remote control when we don't have PV_REMOTE_CONTROL. */ -void pv_remote_init(void) -{ -} - void pv_remote_check( /*@unused@ */ __attribute__((unused)) pvstate_t state) { } -void pv_remote_fini(void) -{ -} int pv_remote_set( /*@unused@ */ __attribute__((unused)) opts_t opts, /*@unused@ */ __attribute__((unused)) pvstate_t state) +{ + /*@-mustfreefresh@ *//* splint - see above */ + pv_error("%s", _("SA_SIGINFO not supported on this system")); + /*@+mustfreefresh@ */ + return PV_ERROREXIT_REMOTE_OR_PID; +} + +#endif /* PV_REMOTE_CONTROL */ + +#ifdef PV_REMOTE_QUERY +/* + * Replace the transfer state with that of the given process, populating + * *sizeptr with that process's idea of the total transfer size if sizeptr + * isn't NULL. + * + * Returns nonzero on error, after reporting the error. + */ +int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_t * sizeptr) +{ + /* TODO: write this */ + return PV_ERROREXIT_REMOTE_OR_PID; +} + +#else /* !PV_REMOTE_QUERY */ + +/* + * Dummy stubs for remote querying when we don't have PV_REMOTE_QUERY. + */ + +int pv_remote_transferstate_fetch( /*@unused@ */ + __attribute__((unused)) pvstate_t state, /*@unused@ */ + __attribute__((unused)) pid_t query, /*@null@ *//*@unused@ */ + __attribute__((unused)) off_t * sizeptr) { /*@-mustfreefresh@ *//* splint - see above */ fprintf(stderr, "%s\n", _("SA_SIGINFO not supported on this system")); @@ -365,4 +377,4 @@ int pv_remote_set( /*@unused@ */ return PV_ERROREXIT_REMOTE_OR_PID; } -#endif /* PV_REMOTE_CONTROL */ +#endif /* PV_REMOTE_QUERY */ diff --git a/src/pv/signal.c b/src/pv/signal.c index c6fd0f9..5bba99b 100644 --- a/src/pv/signal.c +++ b/src/pv/signal.c @@ -263,6 +263,43 @@ bool pv_sigusr2_received(pvstate_t state, pid_t * pid) #endif +#ifdef PV_REMOTE_QUERY +/* + * Handle a SIGUSR1 by setting a flag to say we received it, after recording + * the sending PID. + */ +static void pv_sig_usr1( /*@unused@ */ __attribute__((unused)) + int sig, siginfo_t * info, /*@unused@ */ __attribute__((unused)) + void *ucontext) +{ + if (NULL == pv_sig_state) + return; + if (NULL == info) + return; + pv_sig_state->signal.sender_usr1 = info->si_pid; + pv_sig_state->signal.rxusr1 = 1; +} + + +/* + * Return true if a SIGUSR1 signal has been received since the last time + * this function was called, populating *pid with the sending PID if so. + */ +bool pv_sigusr1_received(pvstate_t state, pid_t * pid) +{ + if (NULL == state) + return false; + if (0 == state->signal.rxusr1) + return false; + if (NULL != pid) + *pid = state->signal.sender_usr1; + state->signal.rxusr1 = 0; + return true; +} + +#endif + + /* * Handle alarm signals by doing nothing. * @@ -390,6 +427,21 @@ void pv_sig_init(pvstate_t state) memset(&sa, 0, sizeof(sa)); #endif +#ifdef PV_REMOTE_QUERY + /* + * Handle SIGUSR1 by setting a flag to say the signal has been + * received, and storing the sending process's PID. + */ + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = pv_sig_usr1; + (void) sigemptyset(&(sa.sa_mask)); + /*@-unrecog@ *//* splint doesn't know about SA_SIGINFO */ + sa.sa_flags = SA_SIGINFO; + /*@+unrecog@ */ + (void) sigaction(SIGUSR1, &sa, &(pv_sig_state->signal.old_sigusr1)); + memset(&sa, 0, sizeof(sa)); +#endif + /* * Ensure that the TOSTOP terminal attribute is set, so that a * SIGTTOU signal will be raised if we try to write to the terminal @@ -433,6 +485,9 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state) (void) sigaction(SIGTERM, &(pv_sig_state->signal.old_sigterm), NULL); #ifdef PV_REMOTE_CONTROL (void) sigaction(SIGUSR2, &(pv_sig_state->signal.old_sigusr2), NULL); +#endif +#ifdef PV_REMOTE_QUERY + (void) sigaction(SIGUSR1, &(pv_sig_state->signal.old_sigusr1), NULL); #endif (void) sigaction(SIGALRM, &(pv_sig_state->signal.old_sigalrm), NULL);