diff --git a/po/de.po b/po/de.po index 03d6e01..6ee7250 100644 --- a/po/de.po +++ b/po/de.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2023-10-14 00:07+0100\n" +"POT-Creation-Date: 2023-10-14 01:21+0100\n" "Language: de\n" "Content-Type: text/plain; charset=UTF-8\n" "Date: 1999-06-01 15:18:29+0100\n" @@ -364,31 +364,31 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:701 src/pv/transfer.c:903 +#: src/pv/display.c:704 src/pv/transfer.c:911 msgid "buffer allocation failed" msgstr "Puffer konnte nicht allokiert werden" -#: src/pv/display.c:763 +#: src/pv/display.c:767 msgid "b" msgstr "" -#: src/pv/display.c:768 src/pv/transfer.c:591 +#: src/pv/display.c:772 src/pv/transfer.c:595 msgid "B" msgstr "B" -#: src/pv/display.c:820 src/pv/display.c:833 +#: src/pv/display.c:825 src/pv/display.c:838 msgid "b/s" msgstr "" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "/s" msgstr "" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "B/s" msgstr "" -#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938 +#: src/pv/display.c:880 src/pv/display.c:884 src/pv/display.c:943 msgid "ETA" msgstr "ETA" @@ -420,7 +420,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:545 src/pv/loop.c:599 src/pv/loop.c:641 src/pv/watchpid.c:73 +#: src/pv/loop.c:546 src/pv/loop.c:601 src/pv/loop.c:643 src/pv/watchpid.c:73 #: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102 #: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158 #: src/pv/watchpid.c:169 src/pv/watchpid.c:256 src/pv/watchpid.c:264 @@ -432,43 +432,43 @@ msgstr "" msgid "history structure allocation failed" msgstr "" -#: src/pv/state.c:385 src/pv/state.c:395 +#: src/pv/state.c:385 src/pv/state.c:396 msgid "file list allocation failed" msgstr "" -#: src/pv/transfer.c:453 +#: src/pv/transfer.c:457 msgid "read failed" msgstr "read-Aufruf fehlgeschlagen" -#: src/pv/transfer.c:476 +#: src/pv/transfer.c:480 msgid "warning: read errors detected" msgstr "warnung: lesefehler erkannt" -#: src/pv/transfer.c:492 +#: src/pv/transfer.c:496 msgid "file is not seekable" msgstr "datei ist nicht durchsuchbar" -#: src/pv/transfer.c:570 +#: src/pv/transfer.c:574 msgid "failed to seek past error" msgstr "konnte den Fehler nicht überwinden" -#: src/pv/transfer.c:590 +#: src/pv/transfer.c:594 msgid "skipped past read error" msgstr "über den Lesefehler hinaus verschoben" -#: src/pv/transfer.c:630 +#: src/pv/transfer.c:634 msgid "no transfer buffer allocated" msgstr "" -#: src/pv/transfer.c:643 +#: src/pv/transfer.c:647 msgid "failed to set alarm signal handler" msgstr "" -#: src/pv/transfer.c:768 +#: src/pv/transfer.c:775 msgid "write failed" msgstr "write-Aufruf fehlgeschlagen" -#: src/pv/transfer.c:1000 +#: src/pv/transfer.c:1008 msgid "select call failed" msgstr "select-Aufruf fehlgeschlagen" diff --git a/po/fr.po b/po/fr.po index f08f3db..7ca0e88 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2023-10-14 00:07+0100\n" +"POT-Creation-Date: 2023-10-14 01:21+0100\n" "Language: fr\n" "Content-Type: text/plain; charset=UTF-8\n" "Date: 1999-06-01 15:18:29+0100\n" @@ -365,31 +365,31 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:701 src/pv/transfer.c:903 +#: src/pv/display.c:704 src/pv/transfer.c:911 msgid "buffer allocation failed" msgstr "l'allocation de mémoire tampon a échoué" -#: src/pv/display.c:763 +#: src/pv/display.c:767 msgid "b" msgstr "" -#: src/pv/display.c:768 src/pv/transfer.c:591 +#: src/pv/display.c:772 src/pv/transfer.c:595 msgid "B" msgstr "O" -#: src/pv/display.c:820 src/pv/display.c:833 +#: src/pv/display.c:825 src/pv/display.c:838 msgid "b/s" msgstr "" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "/s" msgstr "/s" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "B/s" msgstr "O/s" -#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938 +#: src/pv/display.c:880 src/pv/display.c:884 src/pv/display.c:943 msgid "ETA" msgstr "ETA" @@ -421,7 +421,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:545 src/pv/loop.c:599 src/pv/loop.c:641 src/pv/watchpid.c:73 +#: src/pv/loop.c:546 src/pv/loop.c:601 src/pv/loop.c:643 src/pv/watchpid.c:73 #: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102 #: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158 #: src/pv/watchpid.c:169 src/pv/watchpid.c:256 src/pv/watchpid.c:264 @@ -433,43 +433,43 @@ msgstr "" msgid "history structure allocation failed" msgstr "" -#: src/pv/state.c:385 src/pv/state.c:395 +#: src/pv/state.c:385 src/pv/state.c:396 msgid "file list allocation failed" msgstr "" -#: src/pv/transfer.c:453 +#: src/pv/transfer.c:457 msgid "read failed" msgstr "la lecture a échoué" -#: src/pv/transfer.c:476 +#: src/pv/transfer.c:480 msgid "warning: read errors detected" msgstr "avertissement: erreurs de lecture détectées" -#: src/pv/transfer.c:492 +#: src/pv/transfer.c:496 msgid "file is not seekable" msgstr "ne peut pas se déplacer dans le fichier" -#: src/pv/transfer.c:570 +#: src/pv/transfer.c:574 msgid "failed to seek past error" msgstr "n'a pas réussi à dépasser l'erreur" -#: src/pv/transfer.c:590 +#: src/pv/transfer.c:594 msgid "skipped past read error" msgstr "erreur de lecture dépassée" -#: src/pv/transfer.c:630 +#: src/pv/transfer.c:634 msgid "no transfer buffer allocated" msgstr "" -#: src/pv/transfer.c:643 +#: src/pv/transfer.c:647 msgid "failed to set alarm signal handler" msgstr "" -#: src/pv/transfer.c:768 +#: src/pv/transfer.c:775 msgid "write failed" msgstr "l'écriture a échoué" -#: src/pv/transfer.c:1000 +#: src/pv/transfer.c:1008 msgid "select call failed" msgstr "appel de sélection a échoué" diff --git a/po/pl.po b/po/pl.po index cc14e66..475d037 100644 --- a/po/pl.po +++ b/po/pl.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2023-10-14 00:07+0100\n" +"POT-Creation-Date: 2023-10-14 01:21+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -353,31 +353,31 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:701 src/pv/transfer.c:903 +#: src/pv/display.c:704 src/pv/transfer.c:911 msgid "buffer allocation failed" msgstr "nie udało się zaalokować bufora" -#: src/pv/display.c:763 +#: src/pv/display.c:767 msgid "b" msgstr "" -#: src/pv/display.c:768 src/pv/transfer.c:591 +#: src/pv/display.c:772 src/pv/transfer.c:595 msgid "B" msgstr "B" -#: src/pv/display.c:820 src/pv/display.c:833 +#: src/pv/display.c:825 src/pv/display.c:838 msgid "b/s" msgstr "" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "/s" msgstr "/s" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "B/s" msgstr "B/s" -#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938 +#: src/pv/display.c:880 src/pv/display.c:884 src/pv/display.c:943 msgid "ETA" msgstr "ETA" @@ -410,7 +410,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:545 src/pv/loop.c:599 src/pv/loop.c:641 src/pv/watchpid.c:73 +#: src/pv/loop.c:546 src/pv/loop.c:601 src/pv/loop.c:643 src/pv/watchpid.c:73 #: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102 #: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158 #: src/pv/watchpid.c:169 src/pv/watchpid.c:256 src/pv/watchpid.c:264 @@ -422,43 +422,43 @@ msgstr "" msgid "history structure allocation failed" msgstr "" -#: src/pv/state.c:385 src/pv/state.c:395 +#: src/pv/state.c:385 src/pv/state.c:396 msgid "file list allocation failed" msgstr "" -#: src/pv/transfer.c:453 +#: src/pv/transfer.c:457 msgid "read failed" msgstr "błąd odczytu" -#: src/pv/transfer.c:476 +#: src/pv/transfer.c:480 msgid "warning: read errors detected" msgstr "" -#: src/pv/transfer.c:492 +#: src/pv/transfer.c:496 msgid "file is not seekable" msgstr "" -#: src/pv/transfer.c:570 +#: src/pv/transfer.c:574 msgid "failed to seek past error" msgstr "" -#: src/pv/transfer.c:590 +#: src/pv/transfer.c:594 msgid "skipped past read error" msgstr "" -#: src/pv/transfer.c:630 +#: src/pv/transfer.c:634 msgid "no transfer buffer allocated" msgstr "" -#: src/pv/transfer.c:643 +#: src/pv/transfer.c:647 msgid "failed to set alarm signal handler" msgstr "" -#: src/pv/transfer.c:768 +#: src/pv/transfer.c:775 msgid "write failed" msgstr "błąd zapisu" -#: src/pv/transfer.c:1000 +#: src/pv/transfer.c:1008 msgid "select call failed" msgstr "nie udało się wywołać funkcji select" diff --git a/po/pt.po b/po/pt.po index 016bebf..ba0006e 100644 --- a/po/pt.po +++ b/po/pt.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pv@ivarch.com\n" -"POT-Creation-Date: 2023-10-14 00:07+0100\n" +"POT-Creation-Date: 2023-10-14 01:21+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -356,31 +356,31 @@ msgstr "" msgid "yzafpnum KMGTPEZY" msgstr "" -#: src/pv/display.c:701 src/pv/transfer.c:903 +#: src/pv/display.c:704 src/pv/transfer.c:911 msgid "buffer allocation failed" msgstr "erro alocando o buffer" -#: src/pv/display.c:763 +#: src/pv/display.c:767 msgid "b" msgstr "" -#: src/pv/display.c:768 src/pv/transfer.c:591 +#: src/pv/display.c:772 src/pv/transfer.c:595 msgid "B" msgstr "" -#: src/pv/display.c:820 src/pv/display.c:833 +#: src/pv/display.c:825 src/pv/display.c:838 msgid "b/s" msgstr "" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "/s" msgstr "" -#: src/pv/display.c:824 src/pv/display.c:838 +#: src/pv/display.c:829 src/pv/display.c:843 msgid "B/s" msgstr "B/s" -#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938 +#: src/pv/display.c:880 src/pv/display.c:884 src/pv/display.c:943 msgid "ETA" msgstr "ETA" @@ -412,7 +412,7 @@ msgstr "" msgid "(stdin)" msgstr "" -#: src/pv/loop.c:545 src/pv/loop.c:599 src/pv/loop.c:641 src/pv/watchpid.c:73 +#: src/pv/loop.c:546 src/pv/loop.c:601 src/pv/loop.c:643 src/pv/watchpid.c:73 #: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102 #: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158 #: src/pv/watchpid.c:169 src/pv/watchpid.c:256 src/pv/watchpid.c:264 @@ -424,43 +424,43 @@ msgstr "" msgid "history structure allocation failed" msgstr "" -#: src/pv/state.c:385 src/pv/state.c:395 +#: src/pv/state.c:385 src/pv/state.c:396 msgid "file list allocation failed" msgstr "" -#: src/pv/transfer.c:453 +#: src/pv/transfer.c:457 msgid "read failed" msgstr "erro de leitura" -#: src/pv/transfer.c:476 +#: src/pv/transfer.c:480 msgid "warning: read errors detected" msgstr "aviso: erros de leitura detectados" -#: src/pv/transfer.c:492 +#: src/pv/transfer.c:496 msgid "file is not seekable" msgstr "não pode mover dentro do arquivo" -#: src/pv/transfer.c:570 +#: src/pv/transfer.c:574 msgid "failed to seek past error" msgstr "não pode ir além do erro" -#: src/pv/transfer.c:590 +#: src/pv/transfer.c:594 msgid "skipped past read error" msgstr "ignorado erro de leitura" -#: src/pv/transfer.c:630 +#: src/pv/transfer.c:634 msgid "no transfer buffer allocated" msgstr "" -#: src/pv/transfer.c:643 +#: src/pv/transfer.c:647 msgid "failed to set alarm signal handler" msgstr "" -#: src/pv/transfer.c:768 +#: src/pv/transfer.c:775 msgid "write failed" msgstr "erro de gravação" -#: src/pv/transfer.c:1000 +#: src/pv/transfer.c:1008 msgid "select call failed" msgstr "erro na chamada da função select" diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index c5549c0..090f434 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -84,136 +84,154 @@ struct pvcursorstate_s { * Structure for holding PV internal state. Opaque outside the PV library. */ struct pvstate_s { + /****************** + * Program status * + ******************/ + struct { + /*@only@*/ char *program_name; /* program name for error reporting */ + char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */ + int current_input_file; /* index of current file being read */ + int exit_status; /* exit status to give (0=OK) */ + } status; + /*************** * Input files * ***************/ - unsigned int input_file_count; /* number of input files */ - /*@only@*/ /*@null@*/ char **input_files; /* input files */ + struct { + unsigned int file_count; /* number of input files */ + /*@only@*/ /*@null@*/ char **filename; /* input filenames */ + } files; /******************* * Program control * *******************/ - bool force; /* display even if not on terminal */ - bool cursor; /* use cursor positioning */ - bool numeric; /* numeric output only */ - bool wait; /* wait for data before display */ - bool linemode; /* count lines instead of bytes */ - bool bits; /* report bits instead of bytes */ - bool null_terminated_lines; /* lines are null-terminated */ - bool no_display; /* do nothing other than pipe data */ - unsigned int skip_errors; /* skip read errors counter */ - off_t error_skip_block; /* skip block size, 0 for adaptive */ - bool stop_at_size; /* set if we stop at "size" bytes */ - bool sync_after_write; /* set if we sync after every write */ - bool direct_io; /* set if O_DIRECT is to be used */ - bool direct_io_changed; /* set when direct_io is changed */ - bool no_splice; /* never use splice() */ - bool discard_input; /* write nothing to stdout */ - 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 */ - double interval; /* interval between updates */ - double delay_start; /* delay before first display */ - pid_t watch_pid; /* process to watch fds of */ - int watch_fd; /* fd to watch */ - unsigned int width; /* screen width */ - unsigned int height; /* screen height */ - bool width_set_manually; /* width was set manually, not detected */ - bool height_set_manually; /* height was set manually, not detected */ - /*@only@*/ /*@null@*/ char *name; /* display name */ - char default_format[PV_SIZEOF_DEFAULT_FORMAT]; /* default format string */ - /*@only@*/ /*@null@*/ char *format_string; /* output format string */ - - /****************** - * Program status * - ******************/ - /*@only@*/ char *program_name; /* program name for error reporting */ - char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */ - int current_input_file; /* index of current file being read */ - int exit_status; /* exit status to give (0=OK) */ + struct { + bool force; /* display even if not on terminal */ + bool cursor; /* use cursor positioning */ + bool numeric; /* numeric output only */ + bool wait; /* wait for data before display */ + bool linemode; /* count lines instead of bytes */ + bool bits; /* report bits instead of bytes */ + bool null_terminated_lines; /* lines are null-terminated */ + bool no_display; /* do nothing other than pipe data */ + unsigned int skip_errors; /* skip read errors counter */ + off_t error_skip_block; /* skip block size, 0 for adaptive */ + bool stop_at_size; /* set if we stop at "size" bytes */ + bool sync_after_write; /* set if we sync after every write */ + bool direct_io; /* set if O_DIRECT is to be used */ + bool direct_io_changed; /* set when direct_io is changed */ + bool no_splice; /* never use splice() */ + bool discard_input; /* write nothing to stdout */ + 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 */ + double interval; /* interval between updates */ + double delay_start; /* delay before first display */ + pid_t watch_pid; /* process to watch fds of */ + int watch_fd; /* fd to watch */ + unsigned int width; /* screen width */ + unsigned int height; /* screen height */ + bool width_set_manually; /* width was set manually, not detected */ + bool height_set_manually; /* height was set manually, not detected */ + /*@only@*/ /*@null@*/ char *name; /* display name */ + char default_format[PV_SIZEOF_DEFAULT_FORMAT]; /* default format string */ + /*@only@*/ /*@null@*/ char *format_string; /* output format string */ + } control; /******************* * Signal handling * *******************/ - int pv_sig_old_stderr; /* see pv_sig_ttou() */ - bool pv_tty_tostop_added; /* whether we had to set TOSTOP on the terminal */ - struct timespec pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */ - struct timespec pv_sig_toffset; /* total time spent stopped */ - volatile sig_atomic_t pv_sig_newsize; /* whether we need to get term size again */ - volatile sig_atomic_t pv_sig_abort; /* whether we need to abort right now */ - volatile sig_atomic_t reparse_display; /* whether to re-check format string */ + struct { + int old_stderr; /* see pv_sig_ttou() */ + bool pv_tty_tostop_added; /* whether we had to set TOSTOP on the terminal */ + struct timespec tstp_time; /* see pv_sig_tstp() / __cont() */ + struct timespec toffset; /* total time spent stopped */ #ifdef SA_SIGINFO - volatile sig_atomic_t pv_sig_rxusr2; /* whether SIGUSR2 was received */ - volatile pid_t pv_sig_sender; /* PID of sending process for SIGUSR2 */ + volatile sig_atomic_t rxusr2; /* whether SIGUSR2 was received */ + volatile pid_t sender; /* PID of sending process for SIGUSR2 */ #endif - struct sigaction pv_sig_old_sigpipe; - struct sigaction pv_sig_old_sigttou; - struct sigaction pv_sig_old_sigtstp; - struct sigaction pv_sig_old_sigcont; - struct sigaction pv_sig_old_sigwinch; - struct sigaction pv_sig_old_sigint; - struct sigaction pv_sig_old_sighup; - struct sigaction pv_sig_old_sigterm; + struct sigaction old_sigpipe; + struct sigaction old_sigttou; + struct sigaction old_sigtstp; + struct sigaction old_sigcont; + struct sigaction old_sigwinch; + struct sigaction old_sigint; + struct sigaction old_sighup; + struct sigaction old_sigterm; #ifdef SA_SIGINFO - struct sigaction pv_sig_old_sigusr2; + struct sigaction old_sigusr2; #endif + } signal; + + /******************* + * Transient flags * + *******************/ + struct { + volatile sig_atomic_t reparse_display; /* whether to re-check format string */ + volatile sig_atomic_t terminal_resized; /* whether we need to get term size again */ + volatile sig_atomic_t trigger_exit; /* whether we need to abort right now */ + } flag; /***************** * Display state * *****************/ - long percentage; - long double prev_elapsed_sec; - long double prev_rate; - long double prev_trans; - - /* Keep track of progress over last intervals to compute current average rate. */ - /*@null@*/ pvhistory_t *history; /* state at previous intervals (circular buffer) */ - unsigned int history_len; /* total size */ - int history_interval; /* seconds between each history entry */ - int history_first; - int history_last; - long double current_avg_rate; /* current average rate over last history intervals */ - - off_t initial_offset; - /*@only@*/ char *display_buffer; - long display_buffer_size; - size_t lastoutput_length; /* number of last-output bytes to show */ - char lastoutput_buffer[PV_SIZEOF_LASTOUTPUT_BUFFER]; - int prev_width; /* screen width last time we were called */ - int prev_length; /* length of last string we output */ - char str_name[PV_SIZEOF_STR_NAME]; - char str_transferred[PV_SIZEOF_STR_TRANSFERRED]; - char str_bufpercent[PV_SIZEOF_STR_BUFPERCENT]; - char str_timer[PV_SIZEOF_STR_TIMER]; - char str_rate[PV_SIZEOF_STR_RATE]; - char str_average_rate[PV_SIZEOF_STR_AVERAGE_RATE]; - char str_progress[PV_SIZEOF_STR_PROGRESS]; - char str_lastoutput[PV_SIZEOF_STR_LASTOUTPUT]; - char str_eta[PV_SIZEOF_STR_ETA]; - char str_fineta[PV_SIZEOF_STR_FINETA]; - unsigned long components_used; /* bitmask of components used */ struct { - const char *string; - int length; - } format[PV_FORMAT_ARRAY_MAX]; - bool display_visible; /* set once anything written to terminal */ + long percentage; + long double prev_elapsed_sec; + long double prev_rate; + long double prev_trans; + + /* Keep track of progress over last intervals to compute current average rate. */ + /*@null@*/ pvhistory_t *history; /* state at previous intervals (circular buffer) */ + unsigned int history_len; /* total size */ + int history_interval; /* seconds between each history entry */ + int history_first; + int history_last; + long double current_avg_rate; /* current average rate over last history intervals */ + + off_t initial_offset; + /*@only@*/ char *display_buffer; + long display_buffer_size; + size_t lastoutput_length; /* number of last-output bytes to show */ + char lastoutput_buffer[PV_SIZEOF_LASTOUTPUT_BUFFER]; + int prev_width; /* screen width last time we were called */ + int prev_length; /* length of last string we output */ + char str_name[PV_SIZEOF_STR_NAME]; + char str_transferred[PV_SIZEOF_STR_TRANSFERRED]; + char str_bufpercent[PV_SIZEOF_STR_BUFPERCENT]; + char str_timer[PV_SIZEOF_STR_TIMER]; + char str_rate[PV_SIZEOF_STR_RATE]; + char str_average_rate[PV_SIZEOF_STR_AVERAGE_RATE]; + char str_progress[PV_SIZEOF_STR_PROGRESS]; + char str_lastoutput[PV_SIZEOF_STR_LASTOUTPUT]; + char str_eta[PV_SIZEOF_STR_ETA]; + char str_fineta[PV_SIZEOF_STR_FINETA]; + unsigned long components_used; /* bitmask of components used */ + struct { + const char *string; + int length; + } format[PV_FORMAT_ARRAY_MAX]; + bool display_visible; /* set once anything written to terminal */ + } display; /******************** * Cursor/IPC state * ********************/ + struct { #ifdef HAVE_IPC - int crs_shmid; /* ID of our shared memory segment */ - int crs_pvcount; /* number of `pv' processes in total */ - int crs_pvmax; /* highest number of `pv's seen */ - /*@keep@*/ /*@null@*/ struct pvcursorstate_s *crs_shared; /* data shared between instances */ - int crs_y_lastread; /* last value of _y_top seen */ - int crs_y_offset; /* our Y offset from this top position */ - int crs_needreinit; /* counter if we need to reinit cursor pos */ - bool crs_noipc; /* set if we can't use IPC */ + int shmid; /* ID of our shared memory segment */ + int pvcount; /* number of `pv' processes in total */ + int pvmax; /* highest number of `pv's seen */ + /*@keep@*/ /*@null@*/ struct pvcursorstate_s *shared; /* data shared between instances */ + int y_lastread; /* last value of _y_top seen */ + int y_offset; /* our Y offset from this top position */ + int needreinit; /* counter if we need to reinit cursor pos */ + bool noipc; /* set if we can't use IPC */ #endif /* HAVE_IPC */ - int crs_lock_fd; /* fd of lockfile, -1 if none open */ - char crs_lock_file[PV_SIZEOF_CRS_LOCK_FILE]; - int crs_y_start; /* our initial Y coordinate */ + int lock_fd; /* fd of lockfile, -1 if none open */ + char lock_file[PV_SIZEOF_CRS_LOCK_FILE]; + int y_start; /* our initial Y coordinate */ + } cursor; /******************* * Transfer state * @@ -233,40 +251,45 @@ struct pvstate_s { * is the offset in the buffer that we've written data up to. It * will always be less than or equal to read_position. */ - /*@only@*/ /*@null@*/ char *transfer_buffer; /* data transfer buffer */ - size_t buffer_size; /* size of buffer */ - size_t read_position; /* amount of data in buffer */ - size_t write_position; /* buffered data written */ + struct { + /*@only@*/ /*@null@*/ char *transfer_buffer; /* data transfer buffer */ + size_t buffer_size; /* size of buffer */ + size_t read_position; /* amount of data in buffer */ + size_t write_position; /* buffered data written */ - /* - * While reading from a file descriptor we keep track of how many - * times in a row we've seen errors (read_errors_in_a_row), and - * whether or not we have put a warning on stderr about read errors - * on this fd (read_error_warning_shown). - * - * Whenever the active file descriptor changes from - * last_read_skip_fd, we reset read_errors_in_a_row to 0 and - * read_error_warning_shown to false for the new file descriptor and - * set last_read_skip_fd to the new fd number. - * - * This way, we're treating each input file separately. - */ - int last_read_skip_fd; - off_t read_errors_in_a_row; - bool read_error_warning_shown; + /* + * While reading from a file descriptor we keep track of how + * many times in a row we've seen errors + * (read_errors_in_a_row), and whether or not we have put a + * warning on stderr about read errors on this fd + * (read_error_warning_shown). + * + * Whenever the active file descriptor changes from + * last_read_skip_fd, we reset read_errors_in_a_row to 0 and + * read_error_warning_shown to false for the new file + * descriptor and set last_read_skip_fd to the new fd + * number. + * + * This way, we're treating each input file separately. + */ + int last_read_skip_fd; + off_t read_errors_in_a_row; + bool read_error_warning_shown; #ifdef HAVE_SPLICE - /* - * These variables are used to keep track of whether splice() was - * used; splice_failed_fd is the file descriptor that splice() last - * failed on, so that we don't keep trying to use it on an fd that - * doesn't support it, and splice_used is set to true if splice() - * was used this time within pv_transfer(). - */ - int splice_failed_fd; - bool splice_used; + /* + * These variables are used to keep track of whether + * splice() was used; splice_failed_fd is the file + * descriptor that splice() last failed on, so that we don't + * keep trying to use it on an fd that doesn't support it, + * and splice_used is set to true if splice() was used this + * time within pv_transfer(). + */ + int splice_failed_fd; + bool splice_used; #endif - ssize_t to_write; /* max to write this time around */ - ssize_t written; /* bytes sent to stdout this time */ + ssize_t to_write; /* max to write this time around */ + ssize_t written; /* bytes sent to stdout this time */ + } transfer; }; diff --git a/src/pv/cursor.c b/src/pv/cursor.c index 81a88af..74de1eb 100644 --- a/src/pv/cursor.c +++ b/src/pv/cursor.c @@ -79,18 +79,18 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd) char *tmpdir; int openflags; - state->crs_lock_fd = -1; + state->cursor.lock_fd = -1; ttydev = ttyname(fd); if (!ttydev) { - if (!state->force) { + if (!state->control.force) { pv_error(state, "%s: %s", _("failed to get terminal name"), strerror(errno)); } /* * If we don't know our terminal name, we can neither do IPC * nor make a lock file, so turn off cursor positioning. */ - state->cursor = 0; + state->control.cursor = 0; debug("%s", "ttyname failed - cursor positioning disabled"); return; } @@ -104,8 +104,8 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd) */ tmpdir = "/tmp"; - memset(state->crs_lock_file, 0, PV_SIZEOF_CRS_LOCK_FILE); - (void) pv_snprintf(state->crs_lock_file, + memset(state->cursor.lock_file, 0, PV_SIZEOF_CRS_LOCK_FILE); + (void) pv_snprintf(state->cursor.lock_file, PV_SIZEOF_CRS_LOCK_FILE, "%s/pv-%s-%i.lock", tmpdir, basename(ttydev), (int) geteuid()); /* @@ -117,7 +117,7 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd) openflags = O_RDWR | O_CREAT; #endif - state->crs_lock_fd = open(state->crs_lock_file, openflags, 0600); /* flawfinder: ignore */ + state->cursor.lock_fd = open(state->cursor.lock_file, openflags, 0600); /* flawfinder: ignore */ /* * flawfinder rationale: we aren't truncating the lock file, we @@ -126,9 +126,9 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd) * open() is as safe as we can make it. */ - if (state->crs_lock_fd < 0) { - pv_error(state, "%s: %s: %s", state->crs_lock_file, _("failed to open lock file"), strerror(errno)); - state->cursor = 0; + if (state->cursor.lock_fd < 0) { + pv_error(state, "%s: %s: %s", state->cursor.lock_file, _("failed to open lock file"), strerror(errno)); + state->control.cursor = 0; return; } } @@ -144,8 +144,8 @@ static void pv_crs_lock(pvstate_t state, int fd) int lock_fd; lock_fd = fd; - if (state->crs_lock_fd >= 0) - lock_fd = state->crs_lock_fd; + if (state->cursor.lock_fd >= 0) + lock_fd = state->cursor.lock_fd; memset(&lock, 0, sizeof(lock)); lock.l_type = (short) F_WRLCK; @@ -154,10 +154,10 @@ static void pv_crs_lock(pvstate_t state, int fd) lock.l_len = 1; while (fcntl(lock_fd, F_SETLKW, &lock) < 0) { if (errno != EINTR) { - if (state->crs_lock_fd == -2) { + if (state->cursor.lock_fd == -2) { pv_crs_open_lockfile(state, fd); - if (state->crs_lock_fd >= 0) { - lock_fd = state->crs_lock_fd; + if (state->cursor.lock_fd >= 0) { + lock_fd = state->cursor.lock_fd; } } else { pv_error(state, "%s: %s", _("lock attempt failed"), strerror(errno)); @@ -166,8 +166,8 @@ static void pv_crs_lock(pvstate_t state, int fd) } } - if (state->crs_lock_fd >= 0) { - debug("%s: %s", state->crs_lock_file, "terminal lockfile acquired"); + if (state->cursor.lock_fd >= 0) { + debug("%s: %s", state->cursor.lock_file, "terminal lockfile acquired"); } else { debug("%s", "terminal lock acquired"); } @@ -184,8 +184,8 @@ static void pv_crs_unlock(pvstate_t state, int fd) int lock_fd; lock_fd = fd; - if (state->crs_lock_fd >= 0) - lock_fd = state->crs_lock_fd; + if (state->cursor.lock_fd >= 0) + lock_fd = state->cursor.lock_fd; memset(&lock, 0, sizeof(lock)); lock.l_type = (short) F_UNLCK; @@ -194,8 +194,8 @@ static void pv_crs_unlock(pvstate_t state, int fd) lock.l_len = 1; (void) fcntl(lock_fd, F_SETLK, &lock); - if (state->crs_lock_fd >= 0) { - debug("%s: %s", state->crs_lock_file, "terminal lockfile released"); + if (state->cursor.lock_fd >= 0) { + debug("%s: %s", state->cursor.lock_file, "terminal lockfile released"); } else { debug("%s", "terminal lock released"); } @@ -216,13 +216,13 @@ static void pv_crs_ipccount(pvstate_t state) memset(&buf, 0, sizeof(buf)); buf.shm_nattch = 0; - (void) shmctl(state->crs_shmid, IPC_STAT, &buf); - state->crs_pvcount = (int) (buf.shm_nattch); + (void) shmctl(state->cursor.shmid, IPC_STAT, &buf); + state->cursor.pvcount = (int) (buf.shm_nattch); - if (state->crs_pvcount > state->crs_pvmax) - state->crs_pvmax = state->crs_pvcount; + if (state->cursor.pvcount > state->cursor.pvmax) + state->cursor.pvmax = state->cursor.pvcount; - debug("%s: %d", "pvcount", state->crs_pvcount); + debug("%s: %d", "pvcount", state->cursor.pvcount); } #endif /* HAVE_IPC */ @@ -334,13 +334,13 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd) } pv_crs_lock(state, terminalfd); - if (!state->cursor) { + if (!state->control.cursor) { debug("%s", "early return - cursor has been disabled"); return 1; } - state->crs_shmid = shmget(key, sizeof(struct pvcursorstate_s), 0600 | IPC_CREAT); - if (state->crs_shmid < 0) { + state->cursor.shmid = shmget(key, sizeof(struct pvcursorstate_s), 0600 | IPC_CREAT); + if (state->cursor.shmid < 0) { debug("%s: %s", "shmget failed", strerror(errno)); pv_crs_unlock(state, terminalfd); return 1; @@ -348,7 +348,7 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd) /*@-nullpass@ */ /* splint doesn't know shmaddr can be NULL */ - state->crs_shared = shmat(state->crs_shmid, NULL, 0); + state->cursor.shared = shmat(state->cursor.shmid, NULL, 0); /*@+nullpass@ */ pv_crs_ipccount(state); @@ -359,26 +359,26 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd) * current Y cursor co-ordinate and with an initial false value for * the TOSTOP-added flag. */ - if (state->crs_pvcount < 2) { - state->crs_y_start = pv_crs_get_ypos(terminalfd); - state->crs_shared->y_topmost = state->crs_y_start; - state->crs_shared->tty_tostop_added = false; - state->crs_y_lastread = state->crs_y_start; + if (state->cursor.pvcount < 2) { + state->cursor.y_start = pv_crs_get_ypos(terminalfd); + state->cursor.shared->y_topmost = state->cursor.y_start; + state->cursor.shared->tty_tostop_added = false; + state->cursor.y_lastread = state->cursor.y_start; debug("%s", "we are the first to attach"); } - state->crs_y_offset = state->crs_pvcount - 1; - if (state->crs_y_offset < 0) - state->crs_y_offset = 0; + state->cursor.y_offset = state->cursor.pvcount - 1; + if (state->cursor.y_offset < 0) + state->cursor.y_offset = 0; /* * If anyone else had attached to the shared memory segment, we need * to read the top Y co-ordinate from it. */ - if (state->crs_pvcount > 1) { - state->crs_y_start = state->crs_shared->y_topmost; - state->crs_y_lastread = state->crs_y_start; - debug("%s: %d", "not the first to attach - got top y", state->crs_y_start); + if (state->cursor.pvcount > 1) { + state->cursor.y_start = state->cursor.shared->y_topmost; + state->cursor.y_lastread = state->cursor.y_start; + debug("%s: %d", "not the first to attach - got top y", state->cursor.y_start); } pv_crs_unlock(state, terminalfd); @@ -396,10 +396,10 @@ void pv_crs_init(pvstate_t state) char *ttyfile; int terminalfd; - state->crs_lock_fd = -2; - state->crs_lock_file[0] = '\0'; + state->cursor.lock_fd = -2; + state->cursor.lock_file[0] = '\0'; - if (!state->cursor) + if (!state->control.cursor) return; debug("%s", "init"); @@ -407,7 +407,7 @@ void pv_crs_init(pvstate_t state) ttyfile = ttyname(STDERR_FILENO); if (NULL == ttyfile) { debug("%s: %s", "disabling cursor positioning because ttyname failed", strerror(errno)); - state->cursor = false; + state->control.cursor = false; return; } @@ -422,22 +422,22 @@ void pv_crs_init(pvstate_t state) if (terminalfd < 0) { pv_error(state, "%s: %s: %s", _("failed to open terminal"), ttyfile, strerror(errno)); - state->cursor = false; + state->control.cursor = false; return; } #ifdef HAVE_IPC if (pv_crs_ipcinit(state, ttyfile, terminalfd) != 0) { debug("%s", "ipcinit failed, setting noipc flag"); - state->crs_noipc = true; + state->cursor.noipc = true; } /* * If we have already set the terminal TOSTOP attribute, set the * flag in shared memory to let the other instances know. */ - if ((!state->crs_noipc) && state->pv_tty_tostop_added && (NULL != state->crs_shared)) { + if ((!state->cursor.noipc) && state->signal.pv_tty_tostop_added && (NULL != state->cursor.shared)) { debug("%s", "propagating local pv_tty_tostop_added true value to shared flag"); - state->crs_shared->tty_tostop_added = true; + state->cursor.shared->tty_tostop_added = true; } /* @@ -445,7 +445,7 @@ void pv_crs_init(pvstate_t state) * co-ordinate. If we are using IPC, then the pv_crs_ipcinit() * function takes care of this in a more multi-process-friendly way. */ - if (state->crs_noipc) { + if (state->cursor.noipc) { #else /* ! HAVE_IPC */ if (1) { #endif /* HAVE_IPC */ @@ -453,18 +453,18 @@ void pv_crs_init(pvstate_t state) * Get current cursor position + 1. */ pv_crs_lock(state, terminalfd); - state->crs_y_start = pv_crs_get_ypos(terminalfd); + state->cursor.y_start = pv_crs_get_ypos(terminalfd); /* * Move down a line while the terminal is locked, so that * other processes in the pipeline will get a different * initial ypos. */ - if (state->crs_y_start > 0) + if (state->cursor.y_start > 0) pv_write_retry(STDERR_FILENO, "\n", 1); pv_crs_unlock(state, terminalfd); - if (state->crs_y_start < 1) - state->cursor = 0; + if (state->cursor.y_start < 1) + state->control.cursor = 0; } (void) close(terminalfd); @@ -477,9 +477,9 @@ void pv_crs_init(pvstate_t state) */ void pv_crs_needreinit(pvstate_t state) { - state->crs_needreinit += 2; - if (state->crs_needreinit > 3) - state->crs_needreinit = 3; + state->cursor.needreinit += 2; + if (state->cursor.needreinit > 3) + state->cursor.needreinit = 3; } #endif @@ -495,23 +495,23 @@ static void pv_crs_reinit(pvstate_t state) pv_crs_lock(state, STDERR_FILENO); - state->crs_needreinit--; - if (state->crs_y_offset < 1) - state->crs_needreinit = 0; + state->cursor.needreinit--; + if (state->cursor.y_offset < 1) + state->cursor.needreinit = 0; - if (state->crs_needreinit > 0) { + if (state->cursor.needreinit > 0) { pv_crs_unlock(state, STDERR_FILENO); return; } debug("%s", "reinit full"); - state->crs_y_start = pv_crs_get_ypos(STDERR_FILENO); + state->cursor.y_start = pv_crs_get_ypos(STDERR_FILENO); - if ((state->crs_y_offset < 1) && (NULL != state->crs_shared)) { - state->crs_shared->y_topmost = state->crs_y_start; + if ((state->cursor.y_offset < 1) && (NULL != state->cursor.shared)) { + state->cursor.shared->y_topmost = state->cursor.y_start; } - state->crs_y_lastread = state->crs_y_start; + state->cursor.y_lastread = state->cursor.y_start; pv_crs_unlock(state, STDERR_FILENO); } @@ -539,24 +539,24 @@ void pv_crs_update(pvstate_t state, const char *output_line) /* flawfinder - output_line is explictly expected to be \0-terminated. */ #ifdef HAVE_IPC - if (!state->crs_noipc) { - if (state->crs_needreinit > 0) + if (!state->cursor.noipc) { + if (state->cursor.needreinit > 0) pv_crs_reinit(state); pv_crs_ipccount(state); - if (NULL != state->crs_shared) { - if (state->crs_y_lastread != state->crs_shared->y_topmost) { - state->crs_y_start = state->crs_shared->y_topmost; - state->crs_y_lastread = state->crs_y_start; + if (NULL != state->cursor.shared) { + if (state->cursor.y_lastread != state->cursor.shared->y_topmost) { + state->cursor.y_start = state->cursor.shared->y_topmost; + state->cursor.y_lastread = state->cursor.y_start; } } - if (state->crs_needreinit > 0) + if (state->cursor.needreinit > 0) return; } #endif /* HAVE_IPC */ - y = state->crs_y_start; + y = state->cursor.y_start; #ifdef HAVE_IPC /* @@ -565,27 +565,27 @@ void pv_crs_update(pvstate_t state, const char *output_line) * scroll the screen (only if we're the first `pv'), and then move * our initial Y co-ordinate up. */ - if (((state->crs_y_start + state->crs_pvmax) > (int) (state->height)) - && (!state->crs_noipc) + if (((state->cursor.y_start + state->cursor.pvmax) > (int) (state->control.height)) + && (!state->cursor.noipc) ) { int offs; - offs = ((state->crs_y_start + state->crs_pvmax) - state->height); + offs = ((state->cursor.y_start + state->cursor.pvmax) - state->control.height); - state->crs_y_start -= offs; - if (state->crs_y_start < 1) - state->crs_y_start = 1; + state->cursor.y_start -= offs; + if (state->cursor.y_start < 1) + state->cursor.y_start = 1; debug("%s: %d", "scroll offset", offs); /* * Scroll the screen if we're the first `pv'. */ - if (0 == state->crs_y_offset) { + if (0 == state->cursor.y_offset) { pv_crs_lock(state, STDERR_FILENO); memset(cup_cmd, 0, sizeof(cup_cmd)); - (void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%u;1H", state->height); + (void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%u;1H", state->control.height); cup_cmd_length = strlen(cup_cmd); /* flawfinder: ignore */ pv_write_retry(STDERR_FILENO, cup_cmd, cup_cmd_length); for (; offs > 0; offs--) { @@ -598,8 +598,8 @@ void pv_crs_update(pvstate_t state, const char *output_line) } } - if (!state->crs_noipc) - y = state->crs_y_start + state->crs_y_offset; + if (!state->cursor.noipc) + y = state->cursor.y_start + state->cursor.y_offset; #endif /* HAVE_IPC */ /* @@ -641,15 +641,15 @@ void pv_crs_fini(pvstate_t state) debug("%s", "fini"); - y = (unsigned int) (state->crs_y_start); + y = (unsigned int) (state->cursor.y_start); #ifdef HAVE_IPC - if ((state->crs_pvmax > 0) && (!state->crs_noipc)) - y += state->crs_pvmax - 1; + if ((state->cursor.pvmax > 0) && (!state->cursor.noipc)) + y += state->cursor.pvmax - 1; #endif /* HAVE_IPC */ - if (y > state->height) - y = state->height; + if (y > state->control.height) + y = state->control.height; /* * Absolute bounds check. @@ -671,40 +671,40 @@ void pv_crs_fini(pvstate_t state) * attribute, set our local flag so pv_sig_fini() will know about * it. */ - if ((!state->crs_noipc) && (NULL != state->crs_shared) && state->crs_shared->tty_tostop_added) { - if (!state->pv_tty_tostop_added) { + if ((!state->cursor.noipc) && (NULL != state->cursor.shared) && state->cursor.shared->tty_tostop_added) { + if (!state->signal.pv_tty_tostop_added) { debug("%s", "propagating shared tty_tostop_added true value to local flag"); - state->pv_tty_tostop_added = true; + state->signal.pv_tty_tostop_added = true; } } pv_crs_ipccount(state); - if (NULL != state->crs_shared) { - (void) shmdt(state->crs_shared); + if (NULL != state->cursor.shared) { + (void) shmdt(state->cursor.shared); } - state->crs_shared = NULL; + state->cursor.shared = NULL; /* * If we are the last instance detaching from the shared memory, * delete it so it's not left lying around. */ - if (state->crs_pvcount < 2) { + if (state->cursor.pvcount < 2) { struct shmid_ds shm_buf; memset(&shm_buf, 0, sizeof(shm_buf)); - (void) shmctl(state->crs_shmid, IPC_RMID, &shm_buf); + (void) shmctl(state->cursor.shmid, IPC_RMID, &shm_buf); } #endif /* HAVE_IPC */ pv_crs_unlock(state, STDERR_FILENO); - if (state->crs_lock_fd >= 0) { - (void) close(state->crs_lock_fd); + if (state->cursor.lock_fd >= 0) { + (void) close(state->cursor.lock_fd); /* * We can get away with removing this on exit because all * the other PVs will be finishing at the same sort of time. */ - (void) remove(state->crs_lock_file); + (void) remove(state->cursor.lock_file); } } diff --git a/src/pv/display.c b/src/pv/display.c index 67d6adb..766306c 100644 --- a/src/pv/display.c +++ b/src/pv/display.c @@ -42,9 +42,9 @@ void pv_error(pvstate_t state, char *format, ...) { va_list ap; - if (state->display_visible) + if (state->display.display_visible) fprintf(stderr, "\n"); - fprintf(stderr, "%s: ", state->program_name); + fprintf(stderr, "%s: ", state->status.program_name); va_start(ap, format); (void) vfprintf(stderr, format, ap); va_end(ap); @@ -374,22 +374,22 @@ static void pv__format_init(pvstate_t state) if (NULL == state) return; - state->str_name[0] = '\0'; - state->str_transferred[0] = '\0'; - state->str_timer[0] = '\0'; - state->str_rate[0] = '\0'; - state->str_average_rate[0] = '\0'; - state->str_progress[0] = '\0'; - state->str_eta[0] = '\0'; - memset(state->format, 0, PV_FORMAT_ARRAY_MAX * sizeof(state->format[0])); + state->display.str_name[0] = '\0'; + state->display.str_transferred[0] = '\0'; + state->display.str_timer[0] = '\0'; + state->display.str_rate[0] = '\0'; + state->display.str_average_rate[0] = '\0'; + state->display.str_progress[0] = '\0'; + state->display.str_eta[0] = '\0'; + memset(state->display.format, 0, PV_FORMAT_ARRAY_MAX * sizeof(state->display.format[0])); - if (state->name) { - (void) pv_snprintf(state->str_name, PV_SIZEOF_STR_NAME, "%9.500s:", state->name); + if (state->control.name) { + (void) pv_snprintf(state->display.str_name, PV_SIZEOF_STR_NAME, "%9.500s:", state->control.name); } - formatstr = state->format_string ? state->format_string : state->default_format; + formatstr = state->control.format_string ? state->control.format_string : state->control.default_format; - state->components_used = 0; + state->display.components_used = 0; /* * Split the format string into segments. Each segment consists @@ -403,7 +403,7 @@ static void pv__format_init(pvstate_t state) * sized component which will be recalculated by pv__format() * after the length of all fixed-size segments is known, and so * the string is a pointer to another state->str_* buffer - * (currently it will only ever be state->str_progress). + * (currently it will only ever be state->display.str_progress). * * A length above zero indicates that the segment is a constant * string of the given length (not necessarily null terminated). @@ -443,74 +443,74 @@ static void pv__format_init(pvstate_t state) switch (formatstr[strpos]) { case 'p': - state->format[segment].string = state->str_progress; - state->format[segment].length = -1; - state->components_used |= PV_DISPLAY_PROGRESS; + state->display.format[segment].string = state->display.str_progress; + state->display.format[segment].length = -1; + state->display.components_used |= PV_DISPLAY_PROGRESS; break; case 't': - state->format[segment].string = state->str_timer; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_TIMER; + state->display.format[segment].string = state->display.str_timer; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_TIMER; break; case 'e': - state->format[segment].string = state->str_eta; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_ETA; + state->display.format[segment].string = state->display.str_eta; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_ETA; break; case 'I': - state->format[segment].string = state->str_fineta; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_FINETA; + state->display.format[segment].string = state->display.str_fineta; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_FINETA; break; case 'A': - state->format[segment].string = state->str_lastoutput; - state->format[segment].length = 0; + state->display.format[segment].string = state->display.str_lastoutput; + state->display.format[segment].length = 0; if (number_prefix > PV_SIZEOF_LASTOUTPUT_BUFFER) number_prefix = PV_SIZEOF_LASTOUTPUT_BUFFER; if (number_prefix < 1) number_prefix = 1; - state->lastoutput_length = number_prefix; - state->components_used |= PV_DISPLAY_OUTPUTBUF; + state->display.lastoutput_length = number_prefix; + state->display.components_used |= PV_DISPLAY_OUTPUTBUF; break; case 'r': - state->format[segment].string = state->str_rate; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_RATE; + state->display.format[segment].string = state->display.str_rate; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_RATE; break; case 'a': - state->format[segment].string = state->str_average_rate; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_AVERAGERATE; + state->display.format[segment].string = state->display.str_average_rate; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_AVERAGERATE; break; case 'b': - state->format[segment].string = state->str_transferred; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_BYTES; + state->display.format[segment].string = state->display.str_transferred; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_BYTES; break; case 'T': - state->format[segment].string = state->str_bufpercent; - state->format[segment].length = 0; - state->components_used |= PV_DISPLAY_BUFPERCENT; + state->display.format[segment].string = state->display.str_bufpercent; + state->display.format[segment].length = 0; + state->display.components_used |= PV_DISPLAY_BUFPERCENT; break; case 'N': - state->format[segment].string = state->str_name; - state->format[segment].length = (int) strlen(state->str_name); - state->components_used |= PV_DISPLAY_NAME; + state->display.format[segment].string = state->display.str_name; + state->display.format[segment].length = (int) strlen(state->display.str_name); + state->display.components_used |= PV_DISPLAY_NAME; break; case '%': /* %% => % */ - state->format[segment].string = &(formatstr[strpos]); - state->format[segment].length = 1; + state->display.format[segment].string = &(formatstr[strpos]); + state->display.format[segment].length = 1; break; case 0: /* % at end => just % */ - state->format[segment].string = &(formatstr[--strpos]); - state->format[segment].length = 1; + state->display.format[segment].string = &(formatstr[--strpos]); + state->display.format[segment].length = 1; break; default: /* %z (unknown) => %z */ - state->format[segment].string = &(formatstr[--strpos]); - state->format[segment].length = 2; + state->display.format[segment].string = &(formatstr[--strpos]); + state->display.format[segment].length = 2; strpos++; break; } @@ -522,14 +522,14 @@ static void pv__format_init(pvstate_t state) } else { foundlength = searchptr - &(formatstr[strpos]); } - state->format[segment].string = &(formatstr[strpos]); - state->format[segment].length = foundlength; + state->display.format[segment].string = &(formatstr[strpos]); + state->display.format[segment].length = foundlength; strpos += foundlength - 1; } } - state->format[segment].string = 0; - state->format[segment].length = 0; + state->display.format[segment].string = 0; + state->display.format[segment].length = 0; } /* @@ -544,21 +544,21 @@ static long bound_long(long x, long min, long max) /* Update history and current average rate */ static void update_history_avg_rate(pvstate_t state, long long total_bytes, long double elapsed_sec, long double rate) { - int first = state->history_first; - int last = state->history_last; + int first = state->display.history_first; + int last = state->display.history_last; long double last_elapsed; - if (NULL == state->history) + if (NULL == state->display.history) return; - last_elapsed = state->history[last].elapsed_sec; + last_elapsed = state->display.history[last].elapsed_sec; /* * Do nothing if this is not the first call but not enough time has * elapsed since the previous call yet. */ if ((last_elapsed > 0.0) - && (elapsed_sec < (last_elapsed + state->history_interval))) + && (elapsed_sec < (last_elapsed + state->display.history_interval))) return; /* @@ -566,21 +566,23 @@ static void update_history_avg_rate(pvstate_t state, long long total_bytes, long * buffer. */ if (last_elapsed > 0.0) { - int len = state->history_len; - state->history_last = last = (last + 1) % len; + int len = state->display.history_len; + state->display.history_last = last = (last + 1) % len; if (last == first) - state->history_first = first = (first + 1) % len; + state->display.history_first = first = (first + 1) % len; } - state->history[last].elapsed_sec = elapsed_sec; - state->history[last].total_bytes = total_bytes; + state->display.history[last].elapsed_sec = elapsed_sec; + state->display.history[last].total_bytes = total_bytes; if (first == last) { - state->current_avg_rate = rate; + state->display.current_avg_rate = rate; } else { - long long bytes = (state->history[last].total_bytes - state->history[first].total_bytes); - long double sec = (state->history[last].elapsed_sec - state->history[first].elapsed_sec); - state->current_avg_rate = (long double) bytes / sec; + long long bytes = + (state->display.history[last].total_bytes - state->display.history[first].total_bytes); + long double sec = + (state->display.history[last].elapsed_sec - state->display.history[first].elapsed_sec); + state->display.current_avg_rate = (long double) bytes / sec; } } @@ -617,9 +619,9 @@ static const char *pv__format(pvstate_t state, /* Negative total transfer - free memory and exit */ if (total_bytes < 0) { - if (state->display_buffer) - free(state->display_buffer); - state->display_buffer = NULL; + if (state->display.display_buffer) + free(state->display.display_buffer); + state->display.display_buffer = NULL; return NULL; } @@ -629,20 +631,20 @@ static const char *pv__format(pvstate_t state, * adding to that until a reasonable amount of time has passed to * avoid rate spikes or division by zero. */ - time_since_last = elapsed_sec - state->prev_elapsed_sec; + time_since_last = elapsed_sec - state->display.prev_elapsed_sec; if (time_since_last <= 0.01) { - rate = state->prev_rate; - state->prev_trans += bytes_since_last; + rate = state->display.prev_rate; + state->display.prev_trans += bytes_since_last; } else { - rate = ((long double) bytes_since_last + state->prev_trans) / time_since_last; - state->prev_elapsed_sec = elapsed_sec; - state->prev_trans = 0; + rate = ((long double) bytes_since_last + state->display.prev_trans) / time_since_last; + state->display.prev_elapsed_sec = elapsed_sec; + state->display.prev_trans = 0; } - state->prev_rate = rate; + state->display.prev_rate = rate; /* Update history and current average rate for ETA. */ update_history_avg_rate(state, total_bytes, elapsed_sec, rate); - average_rate = state->current_avg_rate; + average_rate = state->display.current_avg_rate; /* * If this is the final update at the end of the transfer, we @@ -654,11 +656,12 @@ static const char *pv__format(pvstate_t state, if (elapsed_sec < 0.000001) elapsed_sec = 0.000001; average_rate = - (((long double) total_bytes) - ((long double) state->initial_offset)) / (long double) elapsed_sec; + (((long double) total_bytes) - + ((long double) state->display.initial_offset)) / (long double) elapsed_sec; rate = average_rate; } - if (state->size <= 0) { + if (state->control.size <= 0) { /* * If we don't know the total size of the incoming data, * then for a percentage, we gradually increase the @@ -668,41 +671,41 @@ static const char *pv__format(pvstate_t state, * 0%-100%, 100%-0%, 0%-100%, and so on. */ if (rate > 0) - state->percentage += 2; - if (state->percentage > 199) - state->percentage = 0; - } else if (state->numeric || ((state->components_used & PV_DISPLAY_PROGRESS) != 0)) { + state->display.percentage += 2; + if (state->display.percentage > 199) + state->display.percentage = 0; + } else if (state->control.numeric || ((state->display.components_used & PV_DISPLAY_PROGRESS) != 0)) { /* * If we do know the total size, and we're going to show * the percentage (numeric mode or a progress bar), * calculate the percentage completion. */ - state->percentage = pv__calc_percentage(total_bytes, state->size); + state->display.percentage = pv__calc_percentage(total_bytes, state->control.size); } /* * Reallocate output buffer if width changes. */ - if (state->display_buffer != NULL && state->display_buffer_size < (state->width * 2)) { - free(state->display_buffer); - state->display_buffer = NULL; - state->display_buffer_size = 0; + if (state->display.display_buffer != NULL && state->display.display_buffer_size < (state->control.width * 2)) { + free(state->display.display_buffer); + state->display.display_buffer = NULL; + state->display.display_buffer_size = 0; } /* * Allocate output buffer if there isn't one. */ - if (NULL == state->display_buffer) { - state->display_buffer_size = (2 * state->width) + 80; - if (state->name) - state->display_buffer_size += strlen(state->name); - state->display_buffer = malloc(state->display_buffer_size + 16); - if (NULL == state->display_buffer) { + if (NULL == state->display.display_buffer) { + state->display.display_buffer_size = (2 * state->control.width) + 80; + if (state->control.name) + state->display.display_buffer_size += strlen(state->control.name); + state->display.display_buffer = malloc(state->display.display_buffer_size + 16); + if (NULL == state->display.display_buffer) { pv_error(state, "%s: %s", _("buffer allocation failed"), strerror(errno)); - state->exit_status |= 64; + state->status.exit_status |= 64; return NULL; } - state->display_buffer[0] = '\0'; + state->display.display_buffer[0] = '\0'; } /* @@ -713,30 +716,31 @@ static const char *pv__format(pvstate_t state, * With --bytes we output the bytes transferred so far instead * of the percentage. (Or lines, if --lines was given with --bytes). */ - if (state->numeric) { + if (state->control.numeric) { char numericprefix[128]; numericprefix[0] = '\0'; - if ((state->components_used & PV_DISPLAY_TIMER) != 0) + if ((state->display.components_used & PV_DISPLAY_TIMER) != 0) (void) pv_snprintf(numericprefix, sizeof(numericprefix), "%.4Lf ", elapsed_sec); - if ((state->components_used & PV_DISPLAY_BYTES) != 0) { - if (state->bits) { - (void) pv_snprintf(state->display_buffer, - state->display_buffer_size, + if ((state->display.components_used & PV_DISPLAY_BYTES) != 0) { + if (state->control.bits) { + (void) pv_snprintf(state->display.display_buffer, + state->display.display_buffer_size, "%.99s%lld\n", numericprefix, 8 * total_bytes); } else { - (void) pv_snprintf(state->display_buffer, - state->display_buffer_size, + (void) pv_snprintf(state->display.display_buffer, + state->display.display_buffer_size, "%.99s%lld\n", numericprefix, total_bytes); } } else { - (void) pv_snprintf(state->display_buffer, - state->display_buffer_size, "%.99s%ld\n", numericprefix, state->percentage); + (void) pv_snprintf(state->display.display_buffer, + state->display.display_buffer_size, "%.99s%ld\n", numericprefix, + state->display.percentage); } - return state->display_buffer; + return state->display.display_buffer; } /* @@ -746,46 +750,47 @@ static const char *pv__format(pvstate_t state, * to be placed in the output buffer. */ - state->str_transferred[0] = '\0'; - state->str_bufpercent[0] = '\0'; - state->str_timer[0] = '\0'; - state->str_rate[0] = '\0'; - state->str_average_rate[0] = '\0'; - state->str_progress[0] = '\0'; - state->str_lastoutput[0] = '\0'; - state->str_eta[0] = '\0'; - state->str_fineta[0] = '\0'; + state->display.str_transferred[0] = '\0'; + state->display.str_bufpercent[0] = '\0'; + state->display.str_timer[0] = '\0'; + state->display.str_rate[0] = '\0'; + state->display.str_average_rate[0] = '\0'; + state->display.str_progress[0] = '\0'; + state->display.str_lastoutput[0] = '\0'; + state->display.str_eta[0] = '\0'; + state->display.str_fineta[0] = '\0'; /* If we're showing bytes transferred, set up the display string. */ - if ((state->components_used & PV_DISPLAY_BYTES) != 0) { - if (state->bits && !state->linemode) { - pv__sizestr(state->str_transferred, + if ((state->display.components_used & PV_DISPLAY_BYTES) != 0) { + if (state->control.bits && !state->control.linemode) { + pv__sizestr(state->display.str_transferred, PV_SIZEOF_STR_TRANSFERRED, "%s", (long double) total_bytes * 8, "", _("b"), PV_TRANSFERCOUNT_BYTES); } else { - pv__sizestr(state->str_transferred, + pv__sizestr(state->display.str_transferred, PV_SIZEOF_STR_TRANSFERRED, "%s", (long double) total_bytes, "", _("B"), - state->linemode ? PV_TRANSFERCOUNT_LINES : PV_TRANSFERCOUNT_BYTES); + state->control.linemode ? PV_TRANSFERCOUNT_LINES : PV_TRANSFERCOUNT_BYTES); } } /* Transfer buffer percentage - set up the display string. */ - if ((state->components_used & PV_DISPLAY_BUFPERCENT) != 0) { - if (state->buffer_size > 0) - (void) pv_snprintf(state->str_bufpercent, + if ((state->display.components_used & PV_DISPLAY_BUFPERCENT) != 0) { + if (state->transfer.buffer_size > 0) + (void) pv_snprintf(state->display.str_bufpercent, PV_SIZEOF_STR_BUFPERCENT, "{%3ld%%}", pv__calc_percentage - (state->read_position - state->write_position, state->buffer_size)); + (state->transfer.read_position - state->transfer.write_position, + state->transfer.buffer_size)); #ifdef HAVE_SPLICE - if (state->splice_used) - (void) pv_snprintf(state->str_bufpercent, PV_SIZEOF_STR_BUFPERCENT, "{%s}", "----"); + if (state->transfer.splice_used) + (void) pv_snprintf(state->display.str_bufpercent, PV_SIZEOF_STR_BUFPERCENT, "{%s}", "----"); #endif } /* Timer - set up the display string. */ - if ((state->components_used & PV_DISPLAY_TIMER) != 0) { + if ((state->display.components_used & PV_DISPLAY_TIMER) != 0) { /* * Bounds check, so we don't overrun the prefix buffer. This * does mean that the timer will stop at a 100,000 hours, @@ -799,14 +804,14 @@ static const char *pv__format(pvstate_t state, * well as hours, minutes, and seconds. */ if (elapsed_sec > (long double) 86400.0L) { - (void) pv_snprintf(state->str_timer, + (void) pv_snprintf(state->display.str_timer, PV_SIZEOF_STR_TIMER, "%ld:%02ld:%02ld:%02ld", ((long) elapsed_sec) / 86400, (((long) elapsed_sec) / 3600) % 24, (((long) elapsed_sec) / 60) % 60, ((long) elapsed_sec) % 60); } else { - (void) pv_snprintf(state->str_timer, + (void) pv_snprintf(state->display.str_timer, PV_SIZEOF_STR_TIMER, "%ld:%02ld:%02ld", ((long) elapsed_sec) / 3600, @@ -815,48 +820,48 @@ static const char *pv__format(pvstate_t state, } /* Rate - set up the display string. */ - if ((state->components_used & PV_DISPLAY_RATE) != 0) { - if (state->bits && !state->linemode) { - pv__sizestr(state->str_rate, PV_SIZEOF_STR_RATE, "[%s]", 8 * rate, "", _("b/s"), + if ((state->display.components_used & PV_DISPLAY_RATE) != 0) { + if (state->control.bits && !state->control.linemode) { + pv__sizestr(state->display.str_rate, PV_SIZEOF_STR_RATE, "[%s]", 8 * rate, "", _("b/s"), PV_TRANSFERCOUNT_BYTES); } else { - pv__sizestr(state->str_rate, + pv__sizestr(state->display.str_rate, PV_SIZEOF_STR_RATE, "[%s]", rate, _("/s"), _("B/s"), - state->linemode ? PV_TRANSFERCOUNT_LINES : PV_TRANSFERCOUNT_BYTES); + state->control.linemode ? PV_TRANSFERCOUNT_LINES : PV_TRANSFERCOUNT_BYTES); } } /* Average rate - set up the display string. */ - if ((state->components_used & PV_DISPLAY_AVERAGERATE) != 0) { - if (state->bits && !state->linemode) { - pv__sizestr(state->str_average_rate, + if ((state->display.components_used & PV_DISPLAY_AVERAGERATE) != 0) { + if (state->control.bits && !state->control.linemode) { + pv__sizestr(state->display.str_average_rate, PV_SIZEOF_STR_AVERAGE_RATE, "[%s]", 8 * average_rate, "", _("b/s"), PV_TRANSFERCOUNT_BYTES); } else { - pv__sizestr(state->str_average_rate, + pv__sizestr(state->display.str_average_rate, PV_SIZEOF_STR_AVERAGE_RATE, "[%s]", average_rate, _("/s"), _("B/s"), - state->linemode ? PV_TRANSFERCOUNT_LINES : PV_TRANSFERCOUNT_BYTES); + state->control.linemode ? PV_TRANSFERCOUNT_LINES : PV_TRANSFERCOUNT_BYTES); } } /* Last output bytes - set up the display string. */ - if ((state->components_used & PV_DISPLAY_OUTPUTBUF) != 0) { + if ((state->display.components_used & PV_DISPLAY_OUTPUTBUF) != 0) { int idx; - for (idx = 0; idx < state->lastoutput_length; idx++) { + for (idx = 0; idx < state->display.lastoutput_length; idx++) { int c; - c = state->lastoutput_buffer[idx]; - state->str_lastoutput[idx] = isprint(c) ? c : '.'; + c = state->display.lastoutput_buffer[idx]; + state->display.str_lastoutput[idx] = isprint(c) ? c : '.'; } - state->str_lastoutput[idx] = '\0'; + state->display.str_lastoutput[idx] = '\0'; } /* ETA (only if size is known) - set up the display string. */ - if (((state->components_used & PV_DISPLAY_ETA) != 0) - && (state->size > 0)) { + if (((state->display.components_used & PV_DISPLAY_ETA) != 0) + && (state->control.size > 0)) { eta = - pv__calc_eta(total_bytes - state->initial_offset, - state->size - state->initial_offset, state->current_avg_rate); + pv__calc_eta(total_bytes - state->display.initial_offset, + state->control.size - state->display.initial_offset, state->display.current_avg_rate); /* * Bounds check, so we don't overrun the suffix buffer. This @@ -869,12 +874,12 @@ static const char *pv__format(pvstate_t state, * well as hours, minutes, and seconds. */ if (eta > 86400L) { - (void) pv_snprintf(state->str_eta, + (void) pv_snprintf(state->display.str_eta, PV_SIZEOF_STR_ETA, "%.16s %ld:%02ld:%02ld:%02ld", _("ETA"), eta / 86400, (eta / 3600) % 24, (eta / 60) % 60, eta % 60); } else { - (void) pv_snprintf(state->str_eta, + (void) pv_snprintf(state->display.str_eta, PV_SIZEOF_STR_ETA, "%.16s %ld:%02ld:%02ld", _("ETA"), eta / 3600, (eta / 60) % 60, eta % 60); } @@ -885,15 +890,15 @@ static const char *pv__format(pvstate_t state, */ if (bytes_since_last < 0) { unsigned int i; - for (i = 0; i < PV_SIZEOF_STR_ETA && state->str_eta[i] != '\0'; i++) { - state->str_eta[i] = ' '; + for (i = 0; i < PV_SIZEOF_STR_ETA && state->display.str_eta[i] != '\0'; i++) { + state->display.str_eta[i] = ' '; } } } /* ETA as clock time (as above) - set up the display string. */ - if (((state->components_used & PV_DISPLAY_FINETA) != 0) - && (state->size > 0)) { + if (((state->display.components_used & PV_DISPLAY_FINETA) != 0) + && (state->control.size > 0)) { /* * The ETA may be hidden by a failed ETA string * generation. @@ -905,8 +910,8 @@ static const char *pv__format(pvstate_t state, char *time_format = NULL; eta = - pv__calc_eta(total_bytes - state->initial_offset, - state->size - state->initial_offset, state->current_avg_rate); + pv__calc_eta(total_bytes - state->display.initial_offset, + state->control.size - state->display.initial_offset, state->display.current_avg_rate); /* * Bounds check, so we don't overrun the suffix buffer. This @@ -935,16 +940,16 @@ static const char *pv__format(pvstate_t state, * by time functions. */ struct tm time = *time_ptr; - (void) pv_snprintf(state->str_fineta, PV_SIZEOF_STR_FINETA, "%.16s ", _("ETA")); - strftime(state->str_fineta + - strlen(state->str_fineta), - PV_SIZEOF_STR_FINETA - 1 - strlen(state->str_fineta), time_format, &time); + (void) pv_snprintf(state->display.str_fineta, PV_SIZEOF_STR_FINETA, "%.16s ", _("ETA")); + strftime(state->display.str_fineta + + strlen(state->display.str_fineta), + PV_SIZEOF_STR_FINETA - 1 - strlen(state->display.str_fineta), time_format, &time); } if (!show_eta) { unsigned int i; - for (i = 0; i < PV_SIZEOF_STR_FINETA && state->str_fineta[i] != '\0'; i++) { - state->str_fineta[i] = ' '; + for (i = 0; i < PV_SIZEOF_STR_FINETA && state->display.str_fineta[i] != '\0'; i++) { + state->display.str_fineta[i] = ' '; } } } @@ -955,13 +960,13 @@ static const char *pv__format(pvstate_t state, * (i.e. the progress bar). */ static_portion_size = 0; - for (segment = 0; state->format[segment].string; segment++) { - if (state->format[segment].length < 0) { + for (segment = 0; state->display.format[segment].string; segment++) { + if (state->display.format[segment].length < 0) { continue; - } else if (state->format[segment].length > 0) { - static_portion_size += state->format[segment].length; + } else if (state->display.format[segment].length > 0) { + static_portion_size += state->display.format[segment].length; } else { - static_portion_size += strlen(state->format[segment].string); + static_portion_size += strlen(state->display.format[segment].string); } } @@ -970,20 +975,20 @@ static const char *pv__format(pvstate_t state, /* * Assemble the progress bar now we know how big it should be. */ - if ((state->components_used & PV_DISPLAY_PROGRESS) != 0) { + if ((state->display.components_used & PV_DISPLAY_PROGRESS) != 0) { char pct[16]; int available_width, i; - strcpy(state->str_progress, "["); + strcpy(state->display.str_progress, "["); - if (state->size > 0) { - if (state->percentage < 0) - state->percentage = 0; - if (state->percentage > 100000) - state->percentage = 100000; - (void) pv_snprintf(pct, sizeof(pct), "%3ld%%", state->percentage); + if (state->control.size > 0) { + if (state->display.percentage < 0) + state->display.percentage = 0; + if (state->display.percentage > 100000) + state->display.percentage = 100000; + (void) pv_snprintf(pct, sizeof(pct), "%3ld%%", state->display.percentage); - available_width = state->width - static_portion_size - strlen(pct) - 3; + available_width = state->control.width - static_portion_size - strlen(pct) - 3; if (available_width < 0) available_width = 0; @@ -991,23 +996,23 @@ static const char *pv__format(pvstate_t state, if (available_width > (int) (PV_SIZEOF_STR_PROGRESS) - 16) available_width = PV_SIZEOF_STR_PROGRESS - 16; - for (i = 0; i < (available_width * state->percentage) / 100 - 1; i++) { + for (i = 0; i < (available_width * state->display.percentage) / 100 - 1; i++) { if (i < available_width) - (void) pv_strlcat(state->str_progress, "=", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, "=", PV_SIZEOF_STR_PROGRESS); } if (i < available_width) { - (void) pv_strlcat(state->str_progress, ">", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, ">", PV_SIZEOF_STR_PROGRESS); i++; } for (; i < available_width; i++) { - (void) pv_strlcat(state->str_progress, " ", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, " ", PV_SIZEOF_STR_PROGRESS); } - (void) pv_strlcat(state->str_progress, "] ", PV_SIZEOF_STR_PROGRESS); - (void) pv_strlcat(state->str_progress, pct, PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, "] ", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, pct, PV_SIZEOF_STR_PROGRESS); } else { - int p = state->percentage; + int p = state->display.percentage; - available_width = state->width - static_portion_size - 5; + available_width = state->control.width - static_portion_size - 5; if (available_width < 0) available_width = 0; @@ -1021,34 +1026,34 @@ static const char *pv__format(pvstate_t state, p = 200 - p; for (i = 0; i < (available_width * p) / 100; i++) { if (i < available_width) - (void) pv_strlcat(state->str_progress, " ", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, " ", PV_SIZEOF_STR_PROGRESS); } - (void) pv_strlcat(state->str_progress, "<=>", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, "<=>", PV_SIZEOF_STR_PROGRESS); for (; i < available_width; i++) { - (void) pv_strlcat(state->str_progress, " ", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, " ", PV_SIZEOF_STR_PROGRESS); } - (void) pv_strlcat(state->str_progress, "]", PV_SIZEOF_STR_PROGRESS); + (void) pv_strlcat(state->display.str_progress, "]", PV_SIZEOF_STR_PROGRESS); } /* * If the progress bar won't fit, drop it. */ - if (strlen(state->str_progress) + static_portion_size > state->width) - state->str_progress[0] = '\0'; + if (strlen(state->display.str_progress) + static_portion_size > state->control.width) + state->display.str_progress[0] = '\0'; } /* * We can now build the output string using the format structure. */ - state->display_buffer[0] = '\0'; + state->display.display_buffer[0] = '\0'; display_string_length = 0; - for (segment = 0; state->format[segment].string; segment++) { + for (segment = 0; state->display.format[segment].string; segment++) { int segment_length; - if (state->format[segment].length > 0) { - segment_length = state->format[segment].length; + if (state->display.format[segment].length > 0) { + segment_length = state->display.format[segment].length; } else { - segment_length = strlen(state->format[segment].string); + segment_length = strlen(state->display.format[segment].string); } /* Skip empty segments */ if (segment_length == 0) @@ -1057,14 +1062,14 @@ static const char *pv__format(pvstate_t state, * Truncate segment if it would make the display string * overflow the buffer */ - if (segment_length + display_string_length > state->display_buffer_size - 2) - segment_length = state->display_buffer_size - display_string_length - 2; + if (segment_length + display_string_length > state->display.display_buffer_size - 2) + segment_length = state->display.display_buffer_size - display_string_length - 2; if (segment_length < 1) break; /* Skip segment if it would make the display too wide */ - if (segment_length + display_string_length > (int) (state->width)) + if (segment_length + display_string_length > (int) (state->control.width)) break; - strncat(state->display_buffer, state->format[segment].string, segment_length); + strncat(state->display.display_buffer, state->display.format[segment].string, segment_length); display_string_length += segment_length; } @@ -1072,12 +1077,12 @@ static const char *pv__format(pvstate_t state, * If the size of our output shrinks, we need to keep appending * spaces at the end, so that we don't leave dangling bits behind. */ - output_length = strlen(state->display_buffer); - if ((output_length < state->prev_length) - && ((int) (state->width) >= state->prev_width)) { + output_length = strlen(state->display.display_buffer); + if ((output_length < state->display.prev_length) + && ((int) (state->control.width) >= state->display.prev_width)) { char spaces[32]; int spaces_to_add; - spaces_to_add = state->prev_length - output_length; + spaces_to_add = state->display.prev_length - output_length; /* Upper boundary on number of spaces */ if (spaces_to_add > 15) { spaces_to_add = 15; @@ -1087,12 +1092,12 @@ static const char *pv__format(pvstate_t state, while (--spaces_to_add >= 0) { spaces[spaces_to_add] = ' '; } - (void) pv_strlcat(state->display_buffer, spaces, state->display_buffer_size); + (void) pv_strlcat(state->display.display_buffer, spaces, state->display.display_buffer_size); } - state->prev_width = state->width; - state->prev_length = output_length; + state->display.prev_width = state->control.width; + state->display.prev_length = output_length; - return state->display_buffer; + return state->display.display_buffer; } @@ -1118,9 +1123,9 @@ void pv_display(pvstate_t state, long double esec, off_t sl, off_t tot) * If the display options need reparsing, do so to generate new * formatting parameters. */ - if (state->reparse_display) { + if (state->flag.reparse_display) { pv__format_init(state); - state->reparse_display = 0; + state->flag.reparse_display = 0; } pv_sig_checkbg(); @@ -1129,18 +1134,18 @@ void pv_display(pvstate_t state, long double esec, off_t sl, off_t tot) if (NULL == display) return; - if (state->numeric) { + if (state->control.numeric) { pv_write_retry(STDERR_FILENO, display, strlen(display)); - } else if (state->cursor) { - if (state->force || pv_in_foreground()) { + } else if (state->control.cursor) { + if (state->control.force || pv_in_foreground()) { pv_crs_update(state, display); - state->display_visible = true; + state->display.display_visible = true; } } else { - if (state->force || pv_in_foreground()) { + if (state->control.force || pv_in_foreground()) { pv_write_retry(STDERR_FILENO, display, strlen(display)); pv_write_retry(STDERR_FILENO, "\r", 1); - state->display_visible = true; + state->display.display_visible = true; } } diff --git a/src/pv/file.c b/src/pv/file.c index d1295fe..1d1e5b5 100644 --- a/src/pv/file.c +++ b/src/pv/file.c @@ -45,25 +45,25 @@ static off_t pv_calc_total_bytes(pvstate_t state) /* * No files specified - check stdin. */ - if ((state->input_file_count < 1) || (NULL == state->input_files)) { + if ((state->files.file_count < 1) || (NULL == state->files.filename)) { if (0 == fstat(STDIN_FILENO, &sb)) total = sb.st_size; return total; } - for (file_idx = 0; file_idx < state->input_file_count; file_idx++) { + for (file_idx = 0; file_idx < state->files.file_count; file_idx++) { int rc; - if (0 == strcmp(state->input_files[file_idx], "-")) { + if (0 == strcmp(state->files.filename[file_idx], "-")) { rc = fstat(STDIN_FILENO, &sb); if (rc != 0) { total = 0; return total; } } else { - rc = stat(state->input_files[file_idx], &sb); + rc = stat(state->files.filename[file_idx], &sb); if (0 == rc) { - rc = access(state->input_files[file_idx], R_OK); /* flawfinder: ignore */ + rc = access(state->files.filename[file_idx], R_OK); /* flawfinder: ignore */ /* * flawfinder rationale: we're not really * using access() to do permissions checks, @@ -79,7 +79,7 @@ static off_t pv_calc_total_bytes(pvstate_t state) } if (rc != 0) { - debug("%s: %s", state->input_files[file_idx], strerror(errno)); + debug("%s: %s", state->files.filename[file_idx], strerror(errno)); total = 0; return total; } @@ -91,7 +91,7 @@ static off_t pv_calc_total_bytes(pvstate_t state) * Get the size of block devices by opening * them and seeking to the end. */ - if (0 == strcmp(state->input_files[file_idx], "-")) { + if (0 == strcmp(state->files.filename[file_idx], "-")) { fd = open("/dev/stdin", O_RDONLY); /* flawfinder: ignore */ /* * flawfinder rationale: "/dev/stdin" may be @@ -101,7 +101,7 @@ static off_t pv_calc_total_bytes(pvstate_t state) * be under the control of someone else. */ } else { - fd = open(state->input_files[file_idx], O_RDONLY); /* flawfinder: ignore */ + fd = open(state->files.filename[file_idx], O_RDONLY); /* flawfinder: ignore */ /* flawfinder - see last open() below. */ } if (fd >= 0) { @@ -146,7 +146,7 @@ static off_t pv_calc_total_bytes(pvstate_t state) if (lseek(STDOUT_FILENO, 0, SEEK_SET) != 0) { pv_error(state, "%s: %s: %s", "(stdout)", _("failed to seek to start of output"), strerror(errno)); - state->exit_status |= 2; + state->status.exit_status |= 2; } /* * If we worked out a size, then set the @@ -155,7 +155,7 @@ static off_t pv_calc_total_bytes(pvstate_t state) * device. */ if (total > 0) { - state->stop_at_size = true; + state->control.stop_at_size = true; } } } @@ -182,11 +182,11 @@ static off_t pv_calc_total_lines(pvstate_t state) total = 0; - for (file_idx = 0; file_idx < state->input_file_count && NULL != state->input_files; file_idx++) { + for (file_idx = 0; file_idx < state->files.file_count && NULL != state->files.filename; file_idx++) { int fd = -1; int rc = 0; - if (0 == strcmp(state->input_files[file_idx], "-")) { + if (0 == strcmp(state->files.filename[file_idx], "-")) { rc = fstat(STDIN_FILENO, &sb); if ((rc != 0) || (!S_ISREG(sb.st_mode))) { total = 0; @@ -194,17 +194,17 @@ static off_t pv_calc_total_lines(pvstate_t state) } fd = dup(STDIN_FILENO); } else { - rc = stat(state->input_files[file_idx], &sb); + rc = stat(state->files.filename[file_idx], &sb); if ((rc != 0) || (!S_ISREG(sb.st_mode))) { total = 0; return total; } - fd = open(state->input_files[file_idx], O_RDONLY); /* flawfinder: ignore */ + fd = open(state->files.filename[file_idx], O_RDONLY); /* flawfinder: ignore */ /* flawfinder - see last open() below. */ } if (fd < 0) { - debug("%s: %s", state->input_files[file_idx], strerror(errno)); + debug("%s: %s", state->files.filename[file_idx], strerror(errno)); total = 0; return total; } @@ -227,14 +227,14 @@ static off_t pv_calc_total_lines(pvstate_t state) * OK. */ if (numread < 0) { - pv_error(state, "%s: %s", state->input_files[file_idx], strerror(errno)); - state->exit_status |= 2; + pv_error(state, "%s: %s", state->files.filename[file_idx], strerror(errno)); + state->status.exit_status |= 2; break; } else if (0 == numread) { break; } for (buf_idx = 0; buf_idx < numread; buf_idx++) { - if (state->null_terminated_lines) { + if (state->control.null_terminated_lines) { if ('\0' == scanbuf[buf_idx]) total++; } else { @@ -245,8 +245,8 @@ static off_t pv_calc_total_lines(pvstate_t state) } if (0 != lseek(fd, 0, SEEK_SET)) { - pv_error(state, "%s: %s", state->input_files[file_idx], strerror(errno)); - state->exit_status |= 2; + pv_error(state, "%s: %s", state->files.filename[file_idx], strerror(errno)); + state->status.exit_status |= 2; } (void) close(fd); @@ -259,13 +259,13 @@ static off_t pv_calc_total_lines(pvstate_t state) /* * Work out the total size of all data by adding up the sizes of all input * files, using either pv_calc_total_bytes() or pv_calc_total_lines() - * depending on whether state->linemode is true. + * depending on whether state->control.linemode is true. * * Returns the total size, or 0 if it is unknown. */ off_t pv_calc_total_size(pvstate_t state) { - if (state->linemode) { + if (state->control.linemode) { return pv_calc_total_lines(state); } else { return pv_calc_total_bytes(state); @@ -279,7 +279,7 @@ off_t pv_calc_total_size(pvstate_t state) * error). It is an error if the next input file is the same as the file * stdout is pointing to. * - * Updates state->current_input_file in the process. + * Updates state->status.current_input_file in the process. */ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) { @@ -291,21 +291,21 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) if (oldfd >= 0) { if (0 != close(oldfd)) { pv_error(state, "%s: %s", _("failed to close file"), strerror(errno)); - state->exit_status |= 8; + state->status.exit_status |= 8; return -1; } } - if (filenum >= state->input_file_count) { - debug("%s: %d >= %d", "filenum too large", filenum, state->input_file_count); - state->exit_status |= 8; + if (filenum >= state->files.file_count) { + debug("%s: %d >= %d", "filenum too large", filenum, state->files.file_count); + state->status.exit_status |= 8; return -1; } - if ((NULL == state->input_files) || (0 == strcmp(state->input_files[filenum], "-"))) { + if ((NULL == state->files.filename) || (0 == strcmp(state->files.filename[filenum], "-"))) { fd = STDIN_FILENO; } else { - fd = open(state->input_files[filenum], O_RDONLY); /* flawfinder: ignore */ + fd = open(state->files.filename[filenum], O_RDONLY); /* flawfinder: ignore */ /* * flawfinder rationale: the input file list is under the * control of the operator by its nature, so we can't refuse @@ -313,24 +313,24 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) */ if (fd < 0) { pv_error(state, "%s: %s: %s", - _("failed to read file"), state->input_files[filenum], strerror(errno)); - state->exit_status |= 2; + _("failed to read file"), state->files.filename[filenum], strerror(errno)); + state->status.exit_status |= 2; return -1; } } if (0 != fstat(fd, &isb)) { pv_error(state, "%s: %s: %s", _("failed to stat file"), - NULL == state->input_files ? "-" : state->input_files[filenum], strerror(errno)); + NULL == state->files.filename ? "-" : state->files.filename[filenum], strerror(errno)); (void) close(fd); - state->exit_status |= 2; + state->status.exit_status |= 2; return -1; } if (0 != fstat(STDOUT_FILENO, &osb)) { pv_error(state, "%s: %s", _("failed to stat output file"), strerror(errno)); (void) close(fd); - state->exit_status |= 2; + state->status.exit_status |= 2; return -1; } @@ -351,18 +351,18 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) if (input_file_is_stdout) { pv_error(state, "%s: %s", _("input file is output file"), - NULL == state->input_files ? "-" : state->input_files[filenum]); + NULL == state->files.filename ? "-" : state->files.filename[filenum]); (void) close(fd); - state->exit_status |= 4; + state->status.exit_status |= 4; return -1; } - state->current_input_file = filenum; + state->status.current_input_file = filenum; #ifdef O_DIRECT /* * Set or clear O_DIRECT on the file descriptor. */ - if (0 != fcntl(fd, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) { + if (0 != fcntl(fd, F_SETFL, (state->control.direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) { /*@-compdef@ */ /* * splint - passed or returned storage is undefined - but at @@ -400,7 +400,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) /*@-statictrans@ */ /* * Here we are doing bad things with regards to whether the returned - * string is an allocated string from the state->input_files array, + * string is an allocated string from the state->files.filename array, * a constant string, or a returned string from gettext(), but it * has no impact. We explicitly document, above, that the returned * string expires with the state, and hence switch off the @@ -418,15 +418,15 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) if (NULL == str_stdin) str_stdin = "(stdin)"; - if (state->current_input_file < 0) + if (state->status.current_input_file < 0) return str_none; - if ((unsigned int) (state->current_input_file) >= state->input_file_count) + if ((unsigned int) (state->status.current_input_file) >= state->files.file_count) return str_none; - if (NULL == state->input_files) { + if (NULL == state->files.filename) { input_file_name = NULL; } else { - input_file_name = state->input_files[state->current_input_file]; + input_file_name = state->files.filename[state->status.current_input_file]; } if (NULL == input_file_name) return str_none; @@ -437,7 +437,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd) return input_file_name; /*@+compdef@ */ /* - * splint warns about state->input_files being undefined, but we + * splint warns about state->files.filename being undefined, but we * know it's been populated fully by the time this function is * called. */ diff --git a/src/pv/loop.c b/src/pv/loop.c index fbf941d..b1d618d 100644 --- a/src/pv/loop.c +++ b/src/pv/loop.c @@ -69,7 +69,7 @@ int pv_main_loop(pvstate_t state) total_written = 0; lineswritten = 0; transferred_since_last = 0; - state->initial_offset = 0; + state->display.initial_offset = 0; memset(&cur_time, 0, sizeof(cur_time)); memset(&start_time, 0, sizeof(start_time)); @@ -84,11 +84,11 @@ int pv_main_loop(pvstate_t state) pv_elapsedtime_copy(&next_ratecheck, &cur_time); pv_elapsedtime_copy(&next_remotecheck, &cur_time); pv_elapsedtime_copy(&next_update, &cur_time); - if ((state->delay_start > 0) - && (state->delay_start > state->interval)) { - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->delay_start)); + if ((state->control.delay_start > 0) + && (state->control.delay_start > state->control.interval)) { + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.delay_start)); } else { - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); } target = 0; @@ -99,7 +99,7 @@ int pv_main_loop(pvstate_t state) * Open the first readable input file. */ fd = -1; - while (fd < 0 && file_idx < state->input_file_count) { + while (fd < 0 && file_idx < state->files.file_count) { fd = pv_next_file(state, file_idx, -1); if (fd < 0) file_idx++; @@ -109,9 +109,9 @@ int pv_main_loop(pvstate_t state) * Exit early if there was no readable input file. */ if (fd < 0) { - if (state->cursor) + if (state->control.cursor) pv_crs_fini(state); - return state->exit_status; + return state->status.exit_status; } #if HAVE_POSIX_FADVISE /* Advise the OS that we will only be reading sequentially. */ @@ -122,10 +122,11 @@ int pv_main_loop(pvstate_t state) /* * Set or clear O_DIRECT on the output. */ - if (0 != fcntl(STDOUT_FILENO, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) { + if (0 != + fcntl(STDOUT_FILENO, F_SETFL, (state->control.direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) { debug("%s: %s", "fcntl", strerror(errno)); } - state->direct_io_changed = false; + state->control.direct_io_changed = false; #endif /* O_DIRECT */ #if HAVE_STRUCT_STAT_ST_BLKSIZE @@ -133,7 +134,7 @@ int pv_main_loop(pvstate_t state) * Set target buffer size if the initial file's block size can be * read and we weren't given a target buffer size. */ - if (0 == state->target_buffer_size) { + if (0 == state->control.target_buffer_size) { struct stat sb; memset(&sb, 0, sizeof(sb)); if (0 == fstat(fd, &sb)) { @@ -142,13 +143,13 @@ int pv_main_loop(pvstate_t state) if (sz > BUFFER_SIZE_MAX) { sz = BUFFER_SIZE_MAX; } - state->target_buffer_size = sz; + state->control.target_buffer_size = sz; } } #endif - if (0 == state->target_buffer_size) - state->target_buffer_size = BUFFER_SIZE; + if (0 == state->control.target_buffer_size) + state->control.target_buffer_size = BUFFER_SIZE; while ((!(eof_in && eof_out)) || (!final_update)) { @@ -162,17 +163,17 @@ int pv_main_loop(pvstate_t state) pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL); } - if (1 == state->pv_sig_abort) + if (1 == state->flag.trigger_exit) break; - if (state->rate_limit > 0) { + if (state->control.rate_limit > 0) { pv_elapsedtime_read(&cur_time); if (pv_elapsedtime_compare(&cur_time, &next_ratecheck) > 0) { target += - ((long double) (state->rate_limit)) / (long double) (1000000000.0 / - (long - double) (RATE_GRANULARITY)); - long double burst_max = ((long double) (state->rate_limit * RATE_BURST_WINDOW)); + ((long double) (state->control.rate_limit)) / (long double) (1000000000.0 / + (long double) + (RATE_GRANULARITY)); + long double burst_max = ((long double) (state->control.rate_limit * RATE_BURST_WINDOW)); if (target > burst_max) { target = burst_max; } @@ -185,11 +186,11 @@ int pv_main_loop(pvstate_t state) * If we have to stop at "size" bytes, make sure we don't * try to write more than we're allowed to. */ - if ((0 < state->size) && (state->stop_at_size)) { - if ((state->size < (total_written + cansend)) + if ((0 < state->control.size) && (state->control.stop_at_size)) { + if ((state->control.size < (total_written + cansend)) || ((0 == cansend) - && (0 == state->rate_limit))) { - cansend = state->size - total_written; + && (0 == state->control.rate_limit))) { + cansend = state->control.size - total_written; if (0 >= cansend) { eof_in = true; eof_out = true; @@ -197,7 +198,7 @@ int pv_main_loop(pvstate_t state) } } - if ((0 < state->size) && (state->stop_at_size) + if ((0 < state->control.size) && (state->control.stop_at_size) && (0 >= cansend) && eof_in && eof_out) { written = 0; } else { @@ -206,27 +207,27 @@ int pv_main_loop(pvstate_t state) /* End on write error. */ if (written < 0) { - if (state->cursor) + if (state->control.cursor) pv_crs_fini(state); - return state->exit_status; + return state->status.exit_status; } - if (state->linemode) { + if (state->control.linemode) { transferred_since_last += lineswritten; total_written += lineswritten; - if (state->rate_limit > 0) + if (state->control.rate_limit > 0) target -= lineswritten; } else { transferred_since_last += written; total_written += written; - if (state->rate_limit > 0) + if (state->control.rate_limit > 0) target -= written; } /* * EOF, and files remain - advance to the next file. */ - while (eof_in && eof_out && file_idx < (state->input_file_count - 1)) { + while (eof_in && eof_out && file_idx < (state->files.file_count - 1)) { file_idx++; fd = pv_next_file(state, file_idx, fd); if (fd >= 0) { @@ -241,14 +242,14 @@ int pv_main_loop(pvstate_t state) /* If full EOF, final update, and force a display updaate. */ if (eof_in && eof_out) { final_update = true; - if ((state->display_visible) - || (state->delay_start < 0.001)) { + if ((state->display.display_visible) + || (state->control.delay_start < 0.001)) { pv_elapsedtime_copy(&next_update, &cur_time); } } /* Just go round the loop again if there's no display. */ - if (state->no_display) + if (state->control.no_display) continue; /* @@ -257,9 +258,9 @@ int pv_main_loop(pvstate_t state) * we then count time as if we started when the first byte * was received. */ - if (state->wait) { + if (state->control.wait) { /* Restart the loop if nothing written yet. */ - if (state->linemode) { + if (state->control.linemode) { if (lineswritten < 1) continue; } else { @@ -267,7 +268,7 @@ int pv_main_loop(pvstate_t state) continue; } - state->wait = 0; + state->control.wait = 0; /* * Reset the timer offset counter now that data @@ -281,7 +282,7 @@ int pv_main_loop(pvstate_t state) */ pv_sig_nopause(); pv_elapsedtime_read(&start_time); - pv_elapsedtime_zero(&(state->pv_sig_toffset)); + pv_elapsedtime_zero(&(state->signal.toffset)); pv_sig_allowpause(); /* @@ -289,7 +290,7 @@ int pv_main_loop(pvstate_t state) * not immediately. */ pv_elapsedtime_copy(&next_update, &start_time); - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); } /* Restart the loop if it's not time to update the display. */ @@ -297,7 +298,7 @@ int pv_main_loop(pvstate_t state) continue; } - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); /* Set the "next update" time to now, if it's in the past. */ if (pv_elapsedtime_compare(&next_update, &cur_time) < 0) @@ -308,7 +309,7 @@ int pv_main_loop(pvstate_t state) * started, plus the total time we spent stopped. */ memset(&init_time, 0, sizeof(init_time)); - pv_elapsedtime_add(&init_time, &start_time, &(state->pv_sig_toffset)); + pv_elapsedtime_add(&init_time, &start_time, &(state->signal.toffset)); /* * Now get the effective elapsed transfer time - current @@ -323,19 +324,19 @@ int pv_main_loop(pvstate_t state) transferred_since_last = -1; /* Resize the display, if a resize signal was received. */ - if (1 == state->pv_sig_newsize) { + if (1 == state->flag.terminal_resized) { unsigned int new_width, new_height; - state->pv_sig_newsize = 0; + state->flag.terminal_resized = 0; - new_width = state->width; - new_height = state->height; + new_width = state->control.width; + new_height = state->control.height; pv_screensize(&new_width, &new_height); - if (!state->width_set_manually) - state->width = new_width; - if (!state->height_set_manually) - state->height = new_height; + if (!state->control.width_set_manually) + state->control.width = new_width; + if (!state->control.height_set_manually) + state->control.height = new_height; } pv_display(state, elapsed_seconds, transferred_since_last, total_written); @@ -343,27 +344,27 @@ int pv_main_loop(pvstate_t state) transferred_since_last = 0; } - if (state->cursor) { + if (state->control.cursor) { pv_crs_fini(state); } else { - if ((!state->numeric) && (!state->no_display) - && (state->display_visible)) + if ((!state->control.numeric) && (!state->control.no_display) + && (state->display.display_visible)) pv_write_retry(STDERR_FILENO, "\n", 1); } - if (1 == state->pv_sig_abort) - state->exit_status |= 32; + if (1 == state->flag.trigger_exit) + state->status.exit_status |= 32; if (fd >= 0) (void) close(fd); - return state->exit_status; + return state->status.exit_status; } /* - * Watch the progress of file descriptor state->watch_fd in process - * state->watch_pid and show details about the transfer on standard error + * Watch the progress of file descriptor state->control.watch_fd in process + * state->control.watch_pid and show details about the transfer on standard error * according to the given options. * * Returns nonzero on error. @@ -379,28 +380,28 @@ int pv_watchfd_loop(pvstate_t state) int rc; memset(&info, 0, sizeof(info)); - info.watch_pid = state->watch_pid; - info.watch_fd = state->watch_fd; + info.watch_pid = state->control.watch_pid; + info.watch_fd = state->control.watch_fd; rc = pv_watchfd_info(state, &info, false); if (0 != rc) { - state->exit_status |= 2; - return state->exit_status; + state->status.exit_status |= 2; + return state->status.exit_status; } /* * Use a size if one was passed, otherwise use the total size * calculated. */ - if (0 >= state->size) - state->size = info.size; + if (0 >= state->control.size) + state->control.size = info.size; - if (state->size < 1) { + if (state->control.size < 1) { char *fmt; - while (NULL != (fmt = strstr(state->default_format, "%e"))) { + while (NULL != (fmt = strstr(state->control.default_format, "%e"))) { debug("%s", "zero size - removing ETA"); /* strlen-1 here to include trailing NUL */ memmove(fmt, fmt + 2, strlen(fmt) - 1); - state->reparse_display = 1; + state->flag.reparse_display = 1; } } @@ -414,7 +415,7 @@ int pv_watchfd_loop(pvstate_t state) pv_elapsedtime_copy(&(info.start_time), &cur_time); pv_elapsedtime_copy(&next_remotecheck, &cur_time); pv_elapsedtime_copy(&next_update, &cur_time); - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); ended = false; total_written = 0; @@ -430,7 +431,7 @@ int pv_watchfd_loop(pvstate_t state) pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL); } - if (1 == state->pv_sig_abort) + if (1 == state->flag.trigger_exit) break; position_now = pv_watchfd_position(&info); @@ -441,7 +442,7 @@ int pv_watchfd_loop(pvstate_t state) transferred_since_last += position_now - total_written; total_written = position_now; if (first_check) { - state->initial_offset = position_now; + state->display.initial_offset = position_now; first_check = false; } } @@ -462,7 +463,7 @@ int pv_watchfd_loop(pvstate_t state) continue; } - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); /* Set the "next update" time to now, if it's in the past. */ if (pv_elapsedtime_compare(&next_update, &cur_time) < 0) @@ -472,7 +473,7 @@ int pv_watchfd_loop(pvstate_t state) * Calculate the effective start time: the time we actually * started, plus the total time we spent stopped. */ - pv_elapsedtime_add(&init_time, &(info.start_time), &(state->pv_sig_toffset)); + pv_elapsedtime_add(&init_time, &(info.start_time), &(state->signal.toffset)); /* * Now get the effective elapsed transfer time - current @@ -486,19 +487,19 @@ int pv_watchfd_loop(pvstate_t state) transferred_since_last = -1; /* Resize the display, if a resize signal was received. */ - if (1 == state->pv_sig_newsize) { + if (1 == state->flag.terminal_resized) { unsigned int new_width, new_height; - state->pv_sig_newsize = 0; + state->flag.terminal_resized = 0; - new_width = state->width; - new_height = state->height; + new_width = state->control.width; + new_height = state->control.height; pv_screensize(&new_width, &new_height); - if (!state->width_set_manually) - state->width = new_width; - if (!state->height_set_manually) - state->height = new_height; + if (!state->control.width_set_manually) + state->control.width = new_width; + if (!state->control.height_set_manually) + state->control.height = new_height; } pv_display(state, elapsed_seconds, transferred_since_last, total_written); @@ -506,18 +507,18 @@ int pv_watchfd_loop(pvstate_t state) transferred_since_last = 0; } - if (!state->numeric) + if (!state->control.numeric) pv_write_retry(STDERR_FILENO, "\n", 1); - if (1 == state->pv_sig_abort) - state->exit_status |= 32; + if (1 == state->flag.trigger_exit) + state->status.exit_status |= 32; - return state->exit_status; + return state->status.exit_status; } /* - * Watch the progress of all file descriptors in process state->watch_pid + * Watch the progress of all file descriptors in process state->control.watch_pid * and show details about the transfers on standard error according to the * given options. * @@ -541,9 +542,9 @@ int pv_watchpid_loop(pvstate_t state) * Make sure the process exists first, so we can give an error if * it's not there at the start. */ - if (kill(state->watch_pid, 0) != 0) { - pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno)); - state->exit_status |= 2; + if (kill(state->control.watch_pid, 0) != 0) { + pv_error(state, "%s %u: %s", _("pid"), state->control.watch_pid, strerror(errno)); + state->status.exit_status |= 2; return 2; } @@ -557,7 +558,8 @@ int pv_watchpid_loop(pvstate_t state) * Make sure there's a format string, and then insert %N into it if * it's not present. */ - original_format_string = state->format_string ? state->format_string : state->default_format; + original_format_string = + state->control.format_string ? state->control.format_string : state->control.default_format; memset(new_format_string, 0, sizeof(new_format_string)); if (NULL == strstr(original_format_string, "%N")) { (void) pv_snprintf(new_format_string, sizeof(new_format_string), "%%N %s", original_format_string); @@ -565,9 +567,9 @@ int pv_watchpid_loop(pvstate_t state) (void) pv_snprintf(new_format_string, sizeof(new_format_string), "%s", original_format_string); } new_format_string[sizeof(new_format_string) - 1] = '\0'; - state_copy.format_string = NULL; - (void) pv_snprintf(state_copy.default_format, PV_SIZEOF_DEFAULT_FORMAT, "%.510s", new_format_string); - state_copy.default_format[PV_SIZEOF_DEFAULT_FORMAT - 1] = '\0'; + state_copy.control.format_string = NULL; + (void) pv_snprintf(state_copy.control.default_format, PV_SIZEOF_DEFAULT_FORMAT, "%.510s", new_format_string); + state_copy.control.default_format[PV_SIZEOF_DEFAULT_FORMAT - 1] = '\0'; /* * Get things ready for the main loop. @@ -578,7 +580,7 @@ int pv_watchpid_loop(pvstate_t state) pv_elapsedtime_read(&cur_time); pv_elapsedtime_copy(&next_update, &cur_time); - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); for (idx = 0; idx < FD_SETSIZE; idx++) { fd_to_idx[idx] = -1; @@ -589,15 +591,15 @@ int pv_watchpid_loop(pvstate_t state) while (true) { int rc, fd, displayed_lines; - if (1 == state->pv_sig_abort) + if (1 == state->flag.trigger_exit) break; pv_elapsedtime_read(&cur_time); - if (kill(state->watch_pid, 0) != 0) { + if (kill(state->control.watch_pid, 0) != 0) { if (first_pass) { - pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno)); - state->exit_status |= 2; + pv_error(state, "%s %u: %s", _("pid"), state->control.watch_pid, strerror(errno)); + state->status.exit_status |= 2; if (NULL != info_array) free(info_array); if (NULL != state_array) @@ -616,30 +618,30 @@ int pv_watchpid_loop(pvstate_t state) continue; } - pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval)); + pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval)); /* Set the "next update" time to now, if it's in the past. */ if (pv_elapsedtime_compare(&next_update, &cur_time) < 0) pv_elapsedtime_copy(&next_update, &cur_time); /* Resize the display, if a resize signal was received. */ - if (1 == state->pv_sig_newsize) { - state->pv_sig_newsize = 0; - pv_screensize(&(state->width), &(state->height)); + if (1 == state->flag.terminal_resized) { + state->flag.terminal_resized = 0; + pv_screensize(&(state->control.width), &(state->control.height)); for (idx = 0; idx < array_length; idx++) { - state_array[idx].width = state->width; - state_array[idx].height = state->height; + state_array[idx].control.width = state->control.width; + state_array[idx].control.height = state->control.height; pv_watchpid_setname(state, &(info_array[idx])); - state_array[idx].reparse_display = 1; + state_array[idx].flag.reparse_display = 1; } } rc = pv_watchpid_scanfds(state, &state_copy, - state->watch_pid, &array_length, &info_array, &state_array, fd_to_idx); + state->control.watch_pid, &array_length, &info_array, &state_array, fd_to_idx); if (rc != 0) { if (first_pass) { - pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno)); - state->exit_status |= 2; + pv_error(state, "%s %u: %s", _("pid"), state->control.watch_pid, strerror(errno)); + state->status.exit_status |= 2; if (NULL != info_array) free(info_array); if (NULL != state_array) @@ -657,7 +659,7 @@ int pv_watchpid_loop(pvstate_t state) struct timespec init_time, transfer_elapsed; long double elapsed_seconds; - if (displayed_lines >= (int) (state->height)) + if (displayed_lines >= (int) (state->control.height)) break; idx = fd_to_idx[fd]; @@ -701,7 +703,7 @@ int pv_watchpid_loop(pvstate_t state) * Calculate the effective start time: the time we actually * started, plus the total time we spent stopped. */ - pv_elapsedtime_add(&init_time, &(info_array[idx].start_time), &(state->pv_sig_toffset)); + pv_elapsedtime_add(&init_time, &(info_array[idx].start_time), &(state->signal.toffset)); /* * Now get the effective elapsed transfer time - current @@ -737,7 +739,7 @@ int pv_watchpid_loop(pvstate_t state) unsigned int x; if (displayed_lines > 0) pv_write_retry(STDERR_FILENO, "\n", 1); - for (x = 0; x < state->width; x++) + for (x = 0; x < state->control.width; x++) pv_write_retry(STDERR_FILENO, " ", 1); pv_write_retry(STDERR_FILENO, "\r", 1); blank_lines--; @@ -758,7 +760,7 @@ int pv_watchpid_loop(pvstate_t state) blank_lines = prev_displayed_lines; while (blank_lines > 0) { unsigned int x; - for (x = 0; x < state->width; x++) + for (x = 0; x < state->control.width; x++) pv_write_retry(STDERR_FILENO, " ", 1); pv_write_retry(STDERR_FILENO, "\r", 1); blank_lines--; diff --git a/src/pv/signal.c b/src/pv/signal.c index fc57e08..ed14808 100644 --- a/src/pv/signal.c +++ b/src/pv/signal.c @@ -45,7 +45,7 @@ static void pv_sig_ensure_tty_tostop() if (0 == (terminal_attributes.c_lflag & TOSTOP)) { terminal_attributes.c_lflag |= TOSTOP; if (0 == tcsetattr(STDERR_FILENO, TCSANOW, &terminal_attributes)) { - pv_sig_state->pv_tty_tostop_added = true; + pv_sig_state->signal.pv_tty_tostop_added = true; debug("%s", "set terminal TOSTOP attribute"); } else { debug("%s: %s", "failed to set terminal TOSTOP attribute", strerror(errno)); @@ -55,8 +55,9 @@ static void pv_sig_ensure_tty_tostop() * In "-c" mode with IPC, make all "pv -c" instances aware * that we set TOSTOP, so the last one can clear it on exit. */ - if (pv_sig_state->cursor && (NULL != pv_sig_state->crs_shared) && (!pv_sig_state->crs_noipc)) { - pv_sig_state->crs_shared->tty_tostop_added = true; + if (pv_sig_state->control.cursor && (NULL != pv_sig_state->cursor.shared) + && (!pv_sig_state->cursor.noipc)) { + pv_sig_state->cursor.shared->tty_tostop_added = true; } #endif } @@ -92,8 +93,8 @@ static void pv_sig_ttou( /*@unused@ */ __attribute__((unused)) * stderr while backgrounded. */ - if (-1 == pv_sig_state->pv_sig_old_stderr) - pv_sig_state->pv_sig_old_stderr = dup(STDERR_FILENO); + if (-1 == pv_sig_state->signal.old_stderr) + pv_sig_state->signal.old_stderr = dup(STDERR_FILENO); if (dup2(fd, STDERR_FILENO) < 0) { debug("%s: %s", "failed to replace stderr", strerror(errno)); @@ -114,7 +115,7 @@ static void pv_sig_tstp( /*@unused@ */ __attribute__((unused)) { if (NULL == pv_sig_state) return; - pv_elapsedtime_read(&(pv_sig_state->pv_sig_tstp_time)); + pv_elapsedtime_read(&(pv_sig_state->signal.tstp_time)); if (0 != raise(SIGSTOP)) { debug("%s: %s", "raise", strerror(errno)); } @@ -135,13 +136,13 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused)) if (NULL == pv_sig_state) return; - pv_sig_state->pv_sig_newsize = 1; + pv_sig_state->flag.terminal_resized = 1; /* * We can only make the time adjustments if this SIGCONT followed a * SIGTSTP such that we have a stop time. */ - if (0 != pv_sig_state->pv_sig_tstp_time.tv_sec) { + if (0 != pv_sig_state->signal.tstp_time.tv_sec) { memset(¤t_time, 0, sizeof(current_time)); memset(&time_spent_stopped, 0, sizeof(time_spent_stopped)); @@ -149,27 +150,27 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused)) pv_elapsedtime_read(¤t_time); /* time spent stopped = current time - time SIGTSTP received */ - pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->pv_sig_tstp_time)); + pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->signal.tstp_time)); /* add time spent stopped the total stopped-time count */ - pv_elapsedtime_add(&(pv_sig_state->pv_sig_toffset), &(pv_sig_state->pv_sig_toffset), + pv_elapsedtime_add(&(pv_sig_state->signal.toffset), &(pv_sig_state->signal.toffset), &time_spent_stopped); /* reset the SIGTSTP receipt time */ - pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time)); + pv_elapsedtime_zero(&(pv_sig_state->signal.tstp_time)); } /* * Restore the old stderr, if we had replaced it. */ - if (pv_sig_state->pv_sig_old_stderr != -1) { - if (dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO) < 0) { + if (pv_sig_state->signal.old_stderr != -1) { + if (dup2(pv_sig_state->signal.old_stderr, STDERR_FILENO) < 0) { debug("%s: %s", "failed to restore old stderr", strerror(errno)); } - if (0 != close(pv_sig_state->pv_sig_old_stderr)) { + if (0 != close(pv_sig_state->signal.old_stderr)) { debug("%s: %s", "failed to close duplicate old stderr", strerror(errno)); } - pv_sig_state->pv_sig_old_stderr = -1; + pv_sig_state->signal.old_stderr = -1; } pv_sig_ensure_tty_tostop(); @@ -189,7 +190,7 @@ static void pv_sig_winch( /*@unused@ */ __attribute__((unused)) { if (NULL == pv_sig_state) return; - pv_sig_state->pv_sig_newsize = 1; + pv_sig_state->flag.terminal_resized = 1; } #endif @@ -202,7 +203,7 @@ static void pv_sig_term( /*@unused@ */ __attribute__((unused)) { if (NULL == pv_sig_state) return; - pv_sig_state->pv_sig_abort = 1; + pv_sig_state->flag.trigger_exit = 1; } @@ -219,8 +220,8 @@ static void pv_sig_usr2( /*@unused@ */ __attribute__((unused)) return; if (NULL == info) return; - pv_sig_state->pv_sig_rxusr2 = 1; - pv_sig_state->pv_sig_sender = info->si_pid; + pv_sig_state->signal.rxusr2 = 1; + pv_sig_state->signal.sender = info->si_pid; } @@ -232,11 +233,11 @@ bool pv_sigusr2_received(pvstate_t state, pid_t * pid) { if (NULL == state) return false; - if (0 == state->pv_sig_rxusr2) + if (0 == state->signal.rxusr2) return false; if (NULL != pid) - *pid = state->pv_sig_sender; - state->pv_sig_rxusr2 = 0; + *pid = state->signal.sender; + state->signal.rxusr2 = 0; return true; } @@ -261,9 +262,9 @@ void pv_sig_init(pvstate_t state) pv_sig_state = state; - pv_sig_state->pv_sig_old_stderr = -1; - pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time)); - pv_elapsedtime_zero(&(pv_sig_state->pv_sig_toffset)); + pv_sig_state->signal.old_stderr = -1; + pv_elapsedtime_zero(&(pv_sig_state->signal.tstp_time)); + pv_elapsedtime_zero(&(pv_sig_state->signal.toffset)); /* * Note that we cast all sigemptyset() and sigaction() return values @@ -278,7 +279,7 @@ void pv_sig_init(pvstate_t state) sa.sa_handler = SIG_IGN; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGPIPE, &sa, &(pv_sig_state->pv_sig_old_sigpipe)); + (void) sigaction(SIGPIPE, &sa, &(pv_sig_state->signal.old_sigpipe)); /* * Handle SIGTTOU by continuing with output switched off, so that we @@ -287,7 +288,7 @@ void pv_sig_init(pvstate_t state) sa.sa_handler = pv_sig_ttou; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGTTOU, &sa, &(pv_sig_state->pv_sig_old_sigttou)); + (void) sigaction(SIGTTOU, &sa, &(pv_sig_state->signal.old_sigttou)); /* * Handle SIGTSTP by storing the time the signal happened for later @@ -296,7 +297,7 @@ void pv_sig_init(pvstate_t state) sa.sa_handler = pv_sig_tstp; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGTSTP, &sa, &(pv_sig_state->pv_sig_old_sigtstp)); + (void) sigaction(SIGTSTP, &sa, &(pv_sig_state->signal.old_sigtstp)); /* * Handle SIGCONT by adding the elapsed time since the last SIGTSTP @@ -306,7 +307,7 @@ void pv_sig_init(pvstate_t state) sa.sa_handler = pv_sig_cont; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGCONT, &sa, &(pv_sig_state->pv_sig_old_sigcont)); + (void) sigaction(SIGCONT, &sa, &(pv_sig_state->signal.old_sigcont)); /* * Handle SIGWINCH by setting a flag to let the main loop know it @@ -316,7 +317,7 @@ void pv_sig_init(pvstate_t state) sa.sa_handler = pv_sig_winch; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGWINCH, &sa, &(pv_sig_state->pv_sig_old_sigwinch)); + (void) sigaction(SIGWINCH, &sa, &(pv_sig_state->signal.old_sigwinch)); #endif /* @@ -326,17 +327,17 @@ void pv_sig_init(pvstate_t state) sa.sa_handler = pv_sig_term; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGINT, &sa, &(pv_sig_state->pv_sig_old_sigint)); + (void) sigaction(SIGINT, &sa, &(pv_sig_state->signal.old_sigint)); sa.sa_handler = pv_sig_term; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGHUP, &sa, &(pv_sig_state->pv_sig_old_sighup)); + (void) sigaction(SIGHUP, &sa, &(pv_sig_state->signal.old_sighup)); sa.sa_handler = pv_sig_term; (void) sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; - (void) sigaction(SIGTERM, &sa, &(pv_sig_state->pv_sig_old_sigterm)); + (void) sigaction(SIGTERM, &sa, &(pv_sig_state->signal.old_sigterm)); #ifdef SA_SIGINFO /* @@ -349,7 +350,7 @@ void pv_sig_init(pvstate_t state) /*@-unrecog@ *//* splint doesn't know about SA_SIGINFO */ sa.sa_flags = SA_SIGINFO; /*@+unrecog@ */ - (void) sigaction(SIGUSR2, &sa, &(pv_sig_state->pv_sig_old_sigusr2)); + (void) sigaction(SIGUSR2, &sa, &(pv_sig_state->signal.old_sigusr2)); memset(&sa, 0, sizeof(sa)); #endif @@ -375,23 +376,23 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state) if (NULL == pv_sig_state) return; - (void) sigaction(SIGPIPE, &(pv_sig_state->pv_sig_old_sigpipe), NULL); - (void) sigaction(SIGTTOU, &(pv_sig_state->pv_sig_old_sigttou), NULL); - (void) sigaction(SIGTSTP, &(pv_sig_state->pv_sig_old_sigtstp), NULL); - (void) sigaction(SIGCONT, &(pv_sig_state->pv_sig_old_sigcont), NULL); + (void) sigaction(SIGPIPE, &(pv_sig_state->signal.old_sigpipe), NULL); + (void) sigaction(SIGTTOU, &(pv_sig_state->signal.old_sigttou), NULL); + (void) sigaction(SIGTSTP, &(pv_sig_state->signal.old_sigtstp), NULL); + (void) sigaction(SIGCONT, &(pv_sig_state->signal.old_sigcont), NULL); #ifdef SIGWINCH - (void) sigaction(SIGWINCH, &(pv_sig_state->pv_sig_old_sigwinch), NULL); + (void) sigaction(SIGWINCH, &(pv_sig_state->signal.old_sigwinch), NULL); #endif - (void) sigaction(SIGINT, &(pv_sig_state->pv_sig_old_sigint), NULL); - (void) sigaction(SIGHUP, &(pv_sig_state->pv_sig_old_sighup), NULL); - (void) sigaction(SIGTERM, &(pv_sig_state->pv_sig_old_sigterm), NULL); + (void) sigaction(SIGINT, &(pv_sig_state->signal.old_sigint), NULL); + (void) sigaction(SIGHUP, &(pv_sig_state->signal.old_sighup), NULL); + (void) sigaction(SIGTERM, &(pv_sig_state->signal.old_sigterm), NULL); #ifdef SA_SIGINFO - (void) sigaction(SIGUSR2, &(pv_sig_state->pv_sig_old_sigusr2), NULL); + (void) sigaction(SIGUSR2, &(pv_sig_state->signal.old_sigusr2), NULL); #endif - need_to_clear_tostop = pv_sig_state->pv_tty_tostop_added; + need_to_clear_tostop = pv_sig_state->signal.pv_tty_tostop_added; - if (pv_sig_state->cursor) { + if (pv_sig_state->control.cursor) { #ifdef HAVE_IPC /* * We won't clear TOSTOP if other "pv -c" instances @@ -400,7 +401,7 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state) * TODO: we need a better way to determine if we're the last * "pv" left. */ - if (pv_sig_state->cursor && pv_sig_state->crs_pvcount > 1) { + if (pv_sig_state->control.cursor && pv_sig_state->cursor.pvcount > 1) { need_to_clear_tostop = false; } #else /* !HAVE_IPC */ @@ -430,7 +431,7 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state) } } - pv_sig_state->pv_tty_tostop_added = false; + pv_sig_state->signal.pv_tty_tostop_added = false; } } @@ -495,18 +496,18 @@ void pv_sig_checkbg(void) next_check = time(NULL) + 1; - if (-1 == pv_sig_state->pv_sig_old_stderr) + if (-1 == pv_sig_state->signal.old_stderr) return; - if (dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO) < 0) { + if (dup2(pv_sig_state->signal.old_stderr, STDERR_FILENO) < 0) { debug("%s: %s", "failed to restore old stderr", strerror(errno)); } - if (0 != close(pv_sig_state->pv_sig_old_stderr)) { + if (0 != close(pv_sig_state->signal.old_stderr)) { debug("%s: %s", "failed to close duplicate old stderr", strerror(errno)); } - pv_sig_state->pv_sig_old_stderr = -1; + pv_sig_state->signal.old_stderr = -1; pv_sig_ensure_tty_tostop(); #ifdef HAVE_IPC diff --git a/src/pv/state.c b/src/pv/state.c index 3bf6bcd..2842e56 100644 --- a/src/pv/state.c +++ b/src/pv/state.c @@ -20,26 +20,26 @@ /* alloc / realloc history buffer */ static void pv_alloc_history(pvstate_t state) { - if (NULL != state->history) - free(state->history); - state->history = NULL; + if (NULL != state->display.history) + free(state->display.history); + state->display.history = NULL; - state->history = calloc((size_t) (state->history_len), sizeof(state->history[0])); - if (NULL == state->history) { + state->display.history = calloc((size_t) (state->display.history_len), sizeof(state->display.history[0])); + if (NULL == state->display.history) { /*@-mustfreefresh@ */ /* * splint note: the gettext calls made by _() cause memory * leak warnings, but in this case it's unavoidable, and * mitigated by the fact we only translate each string once. */ - fprintf(stderr, "%s: %s: %s\n", state->program_name, + fprintf(stderr, "%s: %s: %s\n", state->status.program_name, _("history structure allocation failed"), strerror(errno)); /*@+mustfreefresh@ */ return; } - state->history_first = state->history_last = 0; - state->history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */ + state->display.history_first = state->display.history_last = 0; + state->display.history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */ } /* @@ -55,44 +55,44 @@ pvstate_t pv_state_alloc(const char *program_name) memset(state, 0, sizeof(*state)); /* splint 3.1.2 thinks this is required for some reason. */ - if (NULL != state->program_name) { - free(state->program_name); + if (NULL != state->status.program_name) { + free(state->status.program_name); } - state->program_name = pv_strdup(program_name); - if (NULL == state->program_name) { + state->status.program_name = pv_strdup(program_name); + if (NULL == state->status.program_name) { free(state); return NULL; } - state->watch_pid = 0; - state->watch_fd = -1; + state->control.watch_pid = 0; + state->control.watch_fd = -1; #ifdef HAVE_IPC - state->crs_shmid = -1; - state->crs_pvcount = 1; + state->cursor.shmid = -1; + state->cursor.pvcount = 1; #endif /* HAVE_IPC */ - state->crs_lock_fd = -1; + state->cursor.lock_fd = -1; - state->reparse_display = 1; - state->current_input_file = -1; + state->flag.reparse_display = 1; + state->status.current_input_file = -1; #ifdef HAVE_SPLICE - state->splice_failed_fd = -1; + state->transfer.splice_failed_fd = -1; #endif /* HAVE_SPLICE */ - state->display_visible = false; + state->display.display_visible = false; /* * Get the current working directory, if possible, as a base for * showing relative filenames with --watchfd. */ - if (NULL == getcwd(state->cwd, PV_SIZEOF_CWD - 1)) { + if (NULL == getcwd(state->status.cwd, PV_SIZEOF_CWD - 1)) { /* failed - will always show full path */ - state->cwd[0] = '\0'; + state->status.cwd[0] = '\0'; } - if ('\0' == state->cwd[1]) { + if ('\0' == state->status.cwd[1]) { /* CWD is root directory - always show full path */ - state->cwd[0] = '\0'; + state->status.cwd[0] = '\0'; } - state->cwd[PV_SIZEOF_CWD - 1] = '\0'; + state->status.cwd[PV_SIZEOF_CWD - 1] = '\0'; return state; } @@ -106,45 +106,45 @@ void pv_state_free(pvstate_t state) if (0 == state) return; - if (NULL != state->program_name) - free(state->program_name); - state->program_name = NULL; + if (NULL != state->status.program_name) + free(state->status.program_name); + state->status.program_name = NULL; - if (NULL != state->display_buffer) - free(state->display_buffer); - state->display_buffer = NULL; + if (NULL != state->display.display_buffer) + free(state->display.display_buffer); + state->display.display_buffer = NULL; - if (NULL != state->name) { - free(state->name); - state->name = NULL; + if (NULL != state->control.name) { + free(state->control.name); + state->control.name = NULL; } - if (NULL != state->format_string) { - free(state->format_string); - state->format_string = NULL; + if (NULL != state->control.format_string) { + free(state->control.format_string); + state->control.format_string = NULL; } /*@-keeptrans@ */ - if (NULL != state->transfer_buffer) - free(state->transfer_buffer); - state->transfer_buffer = NULL; + if (NULL != state->transfer.transfer_buffer) + free(state->transfer.transfer_buffer); + state->transfer.transfer_buffer = NULL; /*@+keeptrans@ */ /* splint - explicitly freeing this structure, so free() here is OK. */ - if (NULL != state->history) - free(state->history); - state->history = NULL; + if (NULL != state->display.history) + free(state->display.history); + state->display.history = NULL; - if (NULL != state->input_files) { + if (NULL != state->files.filename) { unsigned int file_idx; - for (file_idx = 0; file_idx < state->input_file_count; file_idx++) { + for (file_idx = 0; file_idx < state->files.file_count; file_idx++) { /*@-unqualifiedtrans@ */ - free(state->input_files[file_idx]); + free(state->files.filename[file_idx]); /*@+unqualifiedtrans@ */ /* splint: see similar code below. */ } - free(state->input_files); - state->input_files = NULL; + free(state->files.filename); + state->files.filename = NULL; } free(state); @@ -160,12 +160,12 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b const char *name) { #define PV_ADDFORMAT(x,y) if (x) { \ - if (state->default_format[0] != '\0') \ - (void) pv_strlcat(state->default_format, " ", sizeof(state->default_format)); \ - (void) pv_strlcat(state->default_format, y, sizeof(state->default_format)); \ + if (state->control.default_format[0] != '\0') \ + (void) pv_strlcat(state->control.default_format, " ", sizeof(state->control.default_format)); \ + (void) pv_strlcat(state->control.default_format, y, sizeof(state->control.default_format)); \ } - state->default_format[0] = '\0'; + state->control.default_format[0] = '\0'; PV_ADDFORMAT(name, "%N"); PV_ADDFORMAT(bytes, "%b"); PV_ADDFORMAT(bufpercent, "%T"); @@ -187,159 +187,159 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b */ } - if (NULL != state->name) { - free(state->name); - state->name = NULL; + if (NULL != state->control.name) { + free(state->control.name); + state->control.name = NULL; } if (NULL != name) - state->name = pv_strdup(name); + state->control.name = pv_strdup(name); - state->reparse_display = 1; + state->flag.reparse_display = 1; } void pv_state_force_set(pvstate_t state, bool val) { - state->force = val; + state->control.force = val; } void pv_state_cursor_set(pvstate_t state, bool val) { - state->cursor = val; + state->control.cursor = val; } void pv_state_numeric_set(pvstate_t state, bool val) { - state->numeric = val; + state->control.numeric = val; } void pv_state_wait_set(pvstate_t state, bool val) { - state->wait = val; + state->control.wait = val; } void pv_state_delay_start_set(pvstate_t state, double val) { - state->delay_start = val; + state->control.delay_start = val; } void pv_state_linemode_set(pvstate_t state, bool val) { - state->linemode = val; + state->control.linemode = val; } void pv_state_bits_set(pvstate_t state, bool bits) { - state->bits = bits; + state->control.bits = bits; } void pv_state_null_terminated_lines_set(pvstate_t state, bool val) { - state->null_terminated_lines = val; + state->control.null_terminated_lines = val; } void pv_state_no_display_set(pvstate_t state, bool val) { - state->no_display = val; + state->control.no_display = val; } void pv_state_skip_errors_set(pvstate_t state, unsigned int val) { - state->skip_errors = val; + state->control.skip_errors = val; } void pv_state_error_skip_block_set(pvstate_t state, off_t val) { - state->error_skip_block = val; + state->control.error_skip_block = val; } void pv_state_stop_at_size_set(pvstate_t state, bool val) { - state->stop_at_size = val; + state->control.stop_at_size = val; } void pv_state_sync_after_write_set(pvstate_t state, bool val) { - state->sync_after_write = val; + state->control.sync_after_write = val; } void pv_state_direct_io_set(pvstate_t state, bool val) { - state->direct_io = val; - state->direct_io_changed = true; + state->control.direct_io = val; + state->control.direct_io_changed = true; } void pv_state_discard_input_set(pvstate_t state, bool val) { - state->discard_input = val; + state->control.discard_input = val; } void pv_state_rate_limit_set(pvstate_t state, off_t val) { - state->rate_limit = val; + state->control.rate_limit = val; } void pv_state_target_buffer_size_set(pvstate_t state, size_t val) { - state->target_buffer_size = val; + state->control.target_buffer_size = val; } void pv_state_no_splice_set(pvstate_t state, bool val) { - state->no_splice = val; + state->control.no_splice = val; } void pv_state_size_set(pvstate_t state, off_t val) { - state->size = val; + state->control.size = val; } void pv_state_interval_set(pvstate_t state, double val) { - state->interval = val; + state->control.interval = val; } void pv_state_width_set(pvstate_t state, unsigned int val, bool was_set_manually) { - state->width = val; - state->width_set_manually = was_set_manually; + state->control.width = val; + state->control.width_set_manually = was_set_manually; } void pv_state_height_set(pvstate_t state, unsigned int val, bool was_set_manually) { - state->height = val; - state->height_set_manually = was_set_manually; + state->control.height = val; + state->control.height_set_manually = was_set_manually; } void pv_state_name_set(pvstate_t state, /*@null@ */ const char *val) { - if (NULL != state->name) { - free(state->name); - state->name = NULL; + if (NULL != state->control.name) { + free(state->control.name); + state->control.name = NULL; } if (NULL != val) - state->name = pv_strdup(val); + state->control.name = pv_strdup(val); } void pv_state_format_string_set(pvstate_t state, /*@null@ */ const char *val) { - if (NULL != state->format_string) { - free(state->format_string); - state->format_string = NULL; + if (NULL != state->control.format_string) { + free(state->control.format_string); + state->control.format_string = NULL; } if (NULL != val) - state->format_string = pv_strdup(val); + state->control.format_string = pv_strdup(val); } void pv_state_watch_pid_set(pvstate_t state, pid_t val) { - state->watch_pid = val; + state->control.watch_pid = val; } void pv_state_watch_fd_set(pvstate_t state, int val) { - state->watch_fd = val; + state->control.watch_fd = val; } void pv_state_average_rate_window_set(pvstate_t state, unsigned int val) @@ -347,11 +347,11 @@ void pv_state_average_rate_window_set(pvstate_t state, unsigned int val) if (val < 1) val = 1; if (val >= 20) { - state->history_len = val / 5 + 1; - state->history_interval = 5; + state->display.history_len = val / 5 + 1; + state->display.history_interval = 5; } else { - state->history_len = val + 1; - state->history_interval = 1; + state->display.history_len = val + 1; + state->display.history_interval = 1; } pv_alloc_history(state); } @@ -364,10 +364,10 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c { unsigned int file_idx; - if (NULL != state->input_files) { - for (file_idx = 0; file_idx < state->input_file_count; file_idx++) { + if (NULL != state->files.filename) { + for (file_idx = 0; file_idx < state->files.file_count; file_idx++) { /*@-unqualifiedtrans@ */ - free(state->input_files[file_idx]); + free(state->files.filename[file_idx]); /*@+unqualifiedtrans@ */ /* * TODO: find a way to tell splint the array @@ -375,29 +375,30 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c * array itself. */ } - free(state->input_files); - state->input_files = NULL; - state->input_file_count = 0; + free(state->files.filename); + state->files.filename = NULL; + state->files.file_count = 0; } - state->input_files = calloc((size_t) (input_file_count + 1), sizeof(char *)); - if (NULL == state->input_files) { + state->files.filename = calloc((size_t) (input_file_count + 1), sizeof(char *)); + if (NULL == state->files.filename) { /*@-mustfreefresh@ *//* see similar _() issue above */ - fprintf(stderr, "%s: %s: %s\n", state->program_name, _("file list allocation failed"), strerror(errno)); + fprintf(stderr, "%s: %s: %s\n", state->status.program_name, _("file list allocation failed"), + strerror(errno)); /*@+mustfreefresh@ */ return; } for (file_idx = 0; file_idx < input_file_count; file_idx++) { /*@-nullstate@ */ - state->input_files[file_idx] = pv_strdup(input_files[file_idx]); - if (NULL == state->input_files[file_idx]) { + state->files.filename[file_idx] = pv_strdup(input_files[file_idx]); + if (NULL == state->files.filename[file_idx]) { /*@-mustfreefresh@ *//* see similar _() issue above */ - fprintf(stderr, "%s: %s: %s\n", state->program_name, + fprintf(stderr, "%s: %s: %s\n", state->status.program_name, _("file list allocation failed"), strerror(errno)); /*@+mustfreefresh@ */ return; } } - state->input_file_count = input_file_count; + state->files.file_count = input_file_count; } /*@+nullstate@*/ diff --git a/src/pv/transfer.c b/src/pv/transfer.c index 8b561f7..66a8546 100644 --- a/src/pv/transfer.c +++ b/src/pv/transfer.c @@ -293,21 +293,21 @@ static ssize_t pv__transfer_write_repeated(int fd, void *buf, size_t count, bool * returns 1. * * At most, the number of bytes read will be the number of bytes remaining - * in the input buffer. If state->rate_limit is >0, and/or "allowed" is >0, + * in the input buffer. If state->control.rate_limit is >0, and/or "allowed" is >0, * then the maximum number of bytes read will be the number remaining unused * in the input buffer or the value of "allowed", whichever is smaller. * - * If splice() was successfully used, sets state->splice_used to true; if it - * failed, then state->splice_failed_fd is updated to the current fd so + * If splice() was successfully used, sets state->transfer.splice_used to true; if it + * failed, then state->transfer.splice_failed_fd is updated to the current fd so * splice() won't be tried again until the next input file. * - * Updates state->read_position by the number of bytes read, unless splice() + * Updates state->transfer.read_position by the number of bytes read, unless splice() * was used, in which case it does not since there's nothing in the buffer - * (and it also adds the bytes to state->written since they've been written + * (and it also adds the bytes to state->transfer.written since they've been written * to the output). * - * On read error, updates state->exit_status, and if allowed by - * state->skip_errors, tries to skip past the problem. + * On read error, updates state->status.exit_status, and if allowed by + * state->control.skip_errors, tries to skip past the problem. * * If the end of the input file is reached or the error is unrecoverable, * sets *eof_in to true. If all data in the buffer has been written at this @@ -324,18 +324,18 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou #endif /* HAVE_SPLICE */ do_not_skip_errors = false; - if (0 == state->skip_errors) + if (0 == state->control.skip_errors) do_not_skip_errors = true; - bytes_can_read = state->buffer_size - state->read_position; + bytes_can_read = state->transfer.buffer_size - state->transfer.read_position; nread = 0; #ifdef HAVE_SPLICE - state->splice_used = false; - if ((!state->linemode) && (!state->no_splice) - && (fd != state->splice_failed_fd) - && (0 == state->to_write)) { - if (state->rate_limit > 0 || allowed != 0) { + state->transfer.splice_used = false; + if ((!state->control.linemode) && (!state->control.no_splice) + && (fd != state->transfer.splice_failed_fd) + && (0 == state->transfer.to_write)) { + if (state->control.rate_limit > 0 || allowed != 0) { bytes_to_splice = (size_t) allowed; } else { bytes_to_splice = bytes_can_read; @@ -348,18 +348,18 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou /*@+type@ */ /*@+nullpass@ */ - state->splice_used = true; + state->transfer.splice_used = true; if ((nread < 0) && (EINVAL == errno)) { debug("%s %d: %s", "fd", fd, "splice failed with EINVAL - disabling"); - state->splice_failed_fd = fd; - state->splice_used = false; + state->transfer.splice_failed_fd = fd; + state->transfer.splice_used = false; /* * Fall through to read() below. */ } else if (nread > 0) { - state->written = nread; + state->transfer.written = nread; #ifdef HAVE_FDATASYNC - if (state->sync_after_write) { + if (state->control.sync_after_write) { /* * Ignore non IO errors, such as EBADFD (bad file * descriptor), EINVAL (non syncable fd, such as a @@ -380,14 +380,18 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou /* nothing read yet - do nothing */ } else { /* EOF might not really be EOF, it seems */ - state->splice_used = false; + state->transfer.splice_used = false; } } - if (!state->splice_used) { - nread = pv__transfer_read_repeated(fd, state->transfer_buffer + state->read_position, bytes_can_read); + if (!state->transfer.splice_used) { + nread = + pv__transfer_read_repeated(fd, state->transfer.transfer_buffer + state->transfer.read_position, + bytes_can_read); } #else - nread = pv__transfer_read_repeated(fd, state->transfer_buffer + state->read_position, bytes_can_read); + nread = + pv__transfer_read_repeated(fd, state->transfer.transfer_buffer + state->transfer.read_position, + bytes_can_read); #endif /* HAVE_SPLICE */ @@ -399,7 +403,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * move on to the next input file. */ *eof_in = true; - if (state->write_position >= state->read_position) + if (state->transfer.write_position >= state->transfer.read_position) *eof_out = true; return 1; } else if (nread > 0) { @@ -408,16 +412,16 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * the error counter and update our record of how much data * we've got in the buffer. */ - state->read_errors_in_a_row = 0; + state->transfer.read_errors_in_a_row = 0; #ifdef HAVE_SPLICE /* * If we used splice(), there isn't any more data in the * buffer than there was before. */ - if (!state->splice_used) - state->read_position += nread; + if (!state->transfer.splice_used) + state->transfer.read_position += nread; #else - state->read_position += nread; + state->transfer.read_position += nread; #endif /* HAVE_SPLICE */ return 1; } @@ -441,8 +445,8 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * exit status, regardless of whether we're skipping errors, and * increment the error counter. */ - state->exit_status |= 16; - state->read_errors_in_a_row++; + state->status.exit_status |= 16; + state->transfer.read_errors_in_a_row++; /* * If we aren't skipping errors, show the error and pretend we @@ -459,7 +463,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * TODO: investigate and fix the reason for this. */ *eof_in = true; - if (state->write_position >= state->read_position) { + if (state->transfer.write_position >= state->transfer.read_position) { *eof_out = true; } return 1; @@ -471,13 +475,13 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou amount_skipped = -1; - if (!state->read_error_warning_shown) { + if (!state->transfer.read_error_warning_shown) { /*@-compdef@ */ pv_error(state, "%s: %s: %s", pv_current_file_name(state), _("warning: read errors detected"), strerror(errno)); /*@+compdef@ */ /* splint - see previous pv_current_file_name() call. */ - state->read_error_warning_shown = true; + state->transfer.read_error_warning_shown = true; } orig_offset = (off_t) lseek(fd, 0, SEEK_CUR); @@ -493,7 +497,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou /*@+compdef@ */ /* splint - see previous pv_current_file_name() calls. */ *eof_in = true; - if (state->write_position >= state->read_position) { + if (state->transfer.write_position >= state->transfer.read_position) { *eof_out = true; } return 1; @@ -504,13 +508,13 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * otherwise start small and ramp up based on the number of errors * in a row. */ - if (state->error_skip_block > 0) { - amount_to_skip = state->error_skip_block; + if (state->control.error_skip_block > 0) { + amount_to_skip = state->control.error_skip_block; } else { - if (state->read_errors_in_a_row < 10) { - amount_to_skip = (off_t) (state->read_errors_in_a_row < 5 ? 1 : 2); - } else if (state->read_errors_in_a_row < 20) { - unsigned int shift_by = (unsigned int) (state->read_errors_in_a_row - 10); + if (state->transfer.read_errors_in_a_row < 10) { + amount_to_skip = (off_t) (state->transfer.read_errors_in_a_row < 5 ? 1 : 2); + } else if (state->transfer.read_errors_in_a_row < 20) { + unsigned int shift_by = (unsigned int) (state->transfer.read_errors_in_a_row - 10); amount_to_skip = (off_t) (1 << shift_by); } else { amount_to_skip = 512; @@ -581,9 +585,9 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * of the transfer buffer, and update the buffer position. */ if (amount_skipped > 0) { - memset(state->transfer_buffer + state->read_position, 0, (size_t) amount_skipped); - state->read_position += amount_skipped; - if (state->skip_errors < 2) { + memset(state->transfer.transfer_buffer + state->transfer.read_position, 0, (size_t) amount_skipped); + state->transfer.read_position += amount_skipped; + if (state->control.skip_errors < 2) { /*@-compdef@ */ pv_error(state, "%s: %s: %ld - %ld (%ld %s)", pv_current_file_name(state), @@ -597,7 +601,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou * Failed to skip - mark file as ended. */ *eof_in = true; - if (state->write_position >= state->read_position) { + if (state->transfer.write_position >= state->transfer.read_position) { *eof_out = true; } } @@ -607,47 +611,48 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou /* - * Write state->to_write bytes of data from the transfer buffer to stdout. + * Write state->transfer.to_write bytes of data from the transfer buffer to stdout. * Returns zero if there was a transient error and we need to return 0 from * pv_transfer, otherwise returns 1. * - * Updates state->write_position by moving it on by the number of bytes - * written; adds the number of bytes written to state->written; sets + * Updates state->transfer.write_position by moving it on by the number of bytes + * written; adds the number of bytes written to state->transfer.written; sets * *eof_out to true, on stdout EOF, or when the write position catches up * with the read position AND *eof_in is true (meaning we've reached the end * of data). * - * On error, sets *eof_out to true, sets state->written to -1, and updates - * state->exit_status. + * On error, sets *eof_out to true, sets state->transfer.written to -1, and updates + * state->status.exit_status. * - * If state->discard_input is true, does not actually write anything. + * If state->control.discard_input is true, does not actually write anything. */ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long *lineswritten) { ssize_t nwritten; - if (NULL == state->transfer_buffer) { + if (NULL == state->transfer.transfer_buffer) { pv_error(state, "%s", _("no transfer buffer allocated")); - state->exit_status |= 64; + state->status.exit_status |= 64; *eof_out = true; - state->written = -1; + state->transfer.written = -1; return 1; } nwritten = 0; - if (state->discard_input) { - nwritten = state->to_write; - } else if (state->to_write > 0) { + if (state->control.discard_input) { + nwritten = state->transfer.to_write; + } else if (state->transfer.to_write > 0) { if (signal(SIGALRM, SIG_IGN) == SIG_ERR) { pv_error(state, "%s: %s", _("failed to set alarm signal handler"), strerror(errno)); } else { (void) alarm(1); } nwritten = pv__transfer_write_repeated(STDOUT_FILENO, - state->transfer_buffer + - state->write_position, (size_t) (state->to_write), - state->sync_after_write); + state->transfer.transfer_buffer + + state->transfer.write_position, + (size_t) (state->transfer.to_write), + state->control.sync_after_write); (void) alarm(0); } @@ -661,20 +666,21 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long /* * Write returned >0 - data successfully written. */ - if ((state->linemode) && (lineswritten != NULL)) { + if ((state->control.linemode) && (lineswritten != NULL)) { char separator; char *ptr; long lines = 0; - if (state->null_terminated_lines) { + if (state->control.null_terminated_lines) { separator = '\0'; } else { separator = '\n'; } - ptr = (char *) (state->transfer_buffer + state->write_position - 1); + ptr = (char *) (state->transfer.transfer_buffer + state->transfer.write_position - 1); for (ptr++; - ptr - (char *) state->transfer_buffer - state->write_position < (size_t) nwritten; ptr++) { + ptr - (char *) state->transfer.transfer_buffer - state->transfer.write_position < + (size_t) nwritten; ptr++) { if (*ptr == separator) ++lines; } @@ -682,37 +688,38 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long *lineswritten += lines; } - state->write_position += nwritten; - state->written += nwritten; + state->transfer.write_position += nwritten; + state->transfer.written += nwritten; /* * If we're monitoring the output, update our copy of the * last few bytes we've written. */ - if (((state->components_used & PV_DISPLAY_OUTPUTBUF) != 0) + if (((state->display.components_used & PV_DISPLAY_OUTPUTBUF) != 0) && (nwritten > 0)) { size_t new_portion_length, old_portion_length; new_portion_length = (size_t) nwritten; - if (new_portion_length > state->lastoutput_length) - new_portion_length = state->lastoutput_length; + if (new_portion_length > state->display.lastoutput_length) + new_portion_length = state->display.lastoutput_length; - old_portion_length = state->lastoutput_length - new_portion_length; + old_portion_length = state->display.lastoutput_length - new_portion_length; /* * Make room for the new portion. */ if (old_portion_length > 0) { - memmove(state->lastoutput_buffer, - state->lastoutput_buffer + new_portion_length, old_portion_length); + memmove(state->display.lastoutput_buffer, + state->display.lastoutput_buffer + new_portion_length, old_portion_length); } /* * Copy the new data in. */ - memcpy(state->lastoutput_buffer + /* flawfinder: ignore */ + memcpy(state->display.lastoutput_buffer + /* flawfinder: ignore */ old_portion_length, - state->transfer_buffer + state->write_position - new_portion_length, new_portion_length); + state->transfer.transfer_buffer + state->transfer.write_position - new_portion_length, + new_portion_length); /* * flawfinder rationale: calculations above ensure * that old_portion_length + new_portion_length is @@ -731,9 +738,9 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long * EOF, set eof_out as well to indicate that we've written * everything for this input file. */ - if (state->write_position >= state->read_position) { - state->write_position = 0; - state->read_position = 0; + if (state->transfer.write_position >= state->transfer.read_position) { + state->transfer.write_position = 0; + state->transfer.read_position = 0; if (*eof_in) *eof_out = true; } @@ -766,9 +773,9 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long } pv_error(state, "%s: %s", _("write failed"), strerror(errno)); - state->exit_status |= 16; + state->status.exit_status |= 16; *eof_out = true; - state->written = -1; + state->transfer.written = -1; return 1; } @@ -841,13 +848,13 @@ static char *pv__allocate_aligned_buffer(int fd, size_t target_size) /* * Transfer some data from "fd" to standard output, timing out after 9/100 - * of a second. If state->rate_limit is >0, and/or "allowed" is >0, only up + * of a second. If state->control.rate_limit is >0, and/or "allowed" is >0, only up * to "allowed" bytes can be written. The variables that "eof_in" and * "eof_out" point to are used to flag that we've finished reading and * writing respectively. * * Returns the number of bytes written, or negative on error (in which case - * state->exit_status is updated). In line mode, the number of lines written + * state->status.exit_status is updated). In line mode, the number of lines written * will be put into *lineswritten. */ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t allowed, long *lineswritten) @@ -864,9 +871,9 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * Set or clear O_DIRECT on the input and output file descriptors, * if the setting has changed. */ - if (state->direct_io_changed) { + if (state->control.direct_io_changed) { if (!(*eof_in)) { - if (0 != fcntl(fd, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) { + if (0 != fcntl(fd, F_SETFL, (state->control.direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) { /*@-compdef@ */ debug("%s: %s: %s", pv_current_file_name(state), "fcntl", strerror(errno)); /*@+compdef@ */ @@ -875,11 +882,11 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t } if (!(*eof_out)) { if (0 != fcntl(STDOUT_FILENO, F_SETFL, - (state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) { + (state->control.direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) { debug("%s: %s: %s", "(stdout)", "fcntl", strerror(errno)); } } - state->direct_io_changed = false; + state->control.direct_io_changed = false; } #endif /* O_DIRECT */ @@ -887,24 +894,25 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * Reinitialise the error skipping variables if the file descriptor * has changed since the last time we were called. */ - if (fd != state->last_read_skip_fd) { - state->last_read_skip_fd = fd; - state->read_errors_in_a_row = 0; - state->read_error_warning_shown = false; + if (fd != state->transfer.last_read_skip_fd) { + state->transfer.last_read_skip_fd = fd; + state->transfer.read_errors_in_a_row = 0; + state->transfer.read_error_warning_shown = false; } /* * Allocate a new buffer, aligned appropriately for the input file * (important if using O_DIRECT). */ - if (NULL == state->transfer_buffer) { - state->transfer_buffer = pv__allocate_aligned_buffer(fd, state->target_buffer_size + 32); - if (NULL == state->transfer_buffer) { + if (NULL == state->transfer.transfer_buffer) { + state->transfer.transfer_buffer = + pv__allocate_aligned_buffer(fd, state->control.target_buffer_size + 32); + if (NULL == state->transfer.transfer_buffer) { pv_error(state, "%s: %s", _("buffer allocation failed"), strerror(errno)); - state->exit_status |= 64; + state->status.exit_status |= 64; return -1; } - state->buffer_size = state->target_buffer_size; + state->transfer.buffer_size = state->control.target_buffer_size; } /* @@ -914,37 +922,37 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * memory) because the buffer may need to be aligned for O_DIRECT, * and we can't realloc() an aligned buffer. */ - if (state->buffer_size < state->target_buffer_size) { + if (state->transfer.buffer_size < state->control.target_buffer_size) { char *newptr; - newptr = pv__allocate_aligned_buffer(fd, state->target_buffer_size + 32); + newptr = pv__allocate_aligned_buffer(fd, state->control.target_buffer_size + 32); if (NULL == newptr) { /* * Reset target if realloc failed so we don't keep * trying to realloc over and over. */ debug("realloc: %s", strerror(errno)); - state->target_buffer_size = state->buffer_size; + state->control.target_buffer_size = state->transfer.buffer_size; } else { - debug("%s: %ld", "buffer resized", state->buffer_size); + debug("%s: %ld", "buffer resized", state->transfer.buffer_size); /* * Copy the old buffer contents into the new buffer, * and free the old one. */ - if (state->buffer_size > 0) { - memcpy(newptr, state->transfer_buffer, state->buffer_size); /* flawfinder: ignore */ + if (state->transfer.buffer_size > 0) { + memcpy(newptr, state->transfer.transfer_buffer, state->transfer.buffer_size); /* flawfinder: ignore */ } /* * flawfinder rationale: number of bytes copied is * definitely always smaller than the new buffer * size. */ - free(state->transfer_buffer); - state->transfer_buffer = newptr; - state->buffer_size = state->target_buffer_size; + free(state->transfer.transfer_buffer); + state->transfer.transfer_buffer = newptr; + state->transfer.buffer_size = state->control.target_buffer_size; } } - if ((state->linemode) && (lineswritten != NULL)) + if ((state->control.linemode) && (lineswritten != NULL)) *lineswritten = 0; if ((*eof_in) && (*eof_out)) @@ -957,7 +965,7 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * If the input file is not at EOF and there's room in the buffer, * look for incoming data from it. */ - if ((!(*eof_in)) && (state->read_position < state->buffer_size)) { + if ((!(*eof_in)) && (state->transfer.read_position < state->transfer.buffer_size)) { check_read_fd = fd; } @@ -967,10 +975,10 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * is >0, then this puts an upper limit on how much we're allowed to * write. */ - state->to_write = (ssize_t) (state->read_position - state->write_position); - if ((state->rate_limit > 0) || (allowed > 0)) { - if ((off_t) (state->to_write) > allowed) { - state->to_write = (ssize_t) allowed; + state->transfer.to_write = (ssize_t) (state->transfer.read_position - state->transfer.write_position); + if ((state->control.rate_limit > 0) || (allowed > 0)) { + if ((off_t) (state->transfer.to_write) > allowed) { + state->transfer.to_write = (ssize_t) allowed; } } @@ -978,7 +986,7 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * If we don't think we've finished writing and there's anything * we're allowed to write, look for the stdout becoming writable. */ - if ((!(*eof_out)) && (state->to_write > 0)) { + if ((!(*eof_out)) && (state->transfer.to_write > 0)) { check_write_fd = STDOUT_FILENO; } @@ -1002,18 +1010,18 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t /*@+compdef@ */ /* splint - see previous pv_current_file_name() calls. */ - state->exit_status |= 16; + state->status.exit_status |= 16; return -1; } - state->written = 0; + state->transfer.written = 0; /* * If there is data to read, try to read some in. Return early if * there was a transient read error. * - * NB this can update state->written because of splice(). + * NB this can update state->transfer.written because of splice(). */ if (ready_to_read) { if (pv__transfer_read(state, fd, eof_in, eof_out, allowed) == 0) @@ -1024,15 +1032,15 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * In line mode, only write up to and including the last newline, * so that we're writing output line-by-line. */ - if ((state->to_write > 0) && (state->linemode) && !(state->null_terminated_lines)) { + if ((state->transfer.to_write > 0) && (state->control.linemode) && !(state->control.null_terminated_lines)) { char *start; char *end; - start = (char *) (state->transfer_buffer + state->write_position); - end = pv_memrchr(start, (int) '\n', (size_t) (state->to_write)); + start = (char *) (state->transfer.transfer_buffer + state->transfer.write_position); + end = pv_memrchr(start, (int) '\n', (size_t) (state->transfer.to_write)); if (NULL != end) { - state->to_write = (ssize_t) ((end - start) + 1); + state->transfer.to_write = (ssize_t) ((end - start) + 1); } } @@ -1043,10 +1051,10 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t */ if (ready_to_write #ifdef HAVE_SPLICE - && (!state->splice_used) + && (!state->transfer.splice_used) #endif /* HAVE_SPLICE */ - && (state->read_position > state->write_position) - && (state->to_write > 0) + && (state->transfer.read_position > state->transfer.write_position) + && (state->transfer.to_write > 0) && (NULL != lineswritten)) { if (pv__transfer_write(state, eof_in, eof_out, lineswritten) == 0) return 0; @@ -1056,21 +1064,22 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t * Rotate the written bytes out of the buffer so that it can be * filled up completely by the next read. */ - if (state->write_position > 0) { - if (state->write_position < state->read_position) { - memmove(state->transfer_buffer, - state->transfer_buffer + - state->write_position, state->read_position - state->write_position); - state->read_position -= state->write_position; - state->write_position = 0; + if (state->transfer.write_position > 0) { + if (state->transfer.write_position < state->transfer.read_position) { + memmove(state->transfer.transfer_buffer, + state->transfer.transfer_buffer + + state->transfer.write_position, + state->transfer.read_position - state->transfer.write_position); + state->transfer.read_position -= state->transfer.write_position; + state->transfer.write_position = 0; } else { - state->write_position = 0; - state->read_position = 0; + state->transfer.write_position = 0; + state->transfer.read_position = 0; } } #endif /* MAXIMISE_BUFFER_FILL */ - return state->written; + return state->transfer.written; } /* EOF */ diff --git a/src/pv/watchpid.c b/src/pv/watchpid.c index 2e3c02c..f94805c 100644 --- a/src/pv/watchpid.c +++ b/src/pv/watchpid.c @@ -385,8 +385,8 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine, *array_length_ptr = array_length; for (check_idx = 0; check_idx < array_length; check_idx++) { - state_array[check_idx].name = info_array[check_idx].display_name; - state_array[check_idx].reparse_display = 1; + state_array[check_idx].control.name = info_array[check_idx].display_name; + state_array[check_idx].flag.reparse_display = 1; } } @@ -427,31 +427,31 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine, info_array[use_idx].watch_fd = -1; } - state_array[use_idx].size = info_array[use_idx].size; - if (state_array[use_idx].size < 1) { + state_array[use_idx].control.size = info_array[use_idx].size; + if (state_array[use_idx].control.size < 1) { char *fmt; - while (NULL != (fmt = strstr(state_array[use_idx].default_format, "%e"))) { + while (NULL != (fmt = strstr(state_array[use_idx].control.default_format, "%e"))) { debug("%s", "zero size - removing ETA"); /* strlen-1 here to include trailing NUL */ memmove(fmt, fmt + 2, strlen(fmt) - 1); - state_array[use_idx].reparse_display = 1; + state_array[use_idx].flag.reparse_display = 1; } } - state_array[use_idx].name = info_array[use_idx].display_name; + state_array[use_idx].control.name = info_array[use_idx].display_name; pv_watchpid_setname(state, &(info_array[use_idx])); - state_array[use_idx].reparse_display = 1; + state_array[use_idx].flag.reparse_display = 1; pv_elapsedtime_read(&(info_array[use_idx].start_time)); - state_array[use_idx].initial_offset = 0; + state_array[use_idx].display.initial_offset = 0; info_array[use_idx].position = 0; position_now = pv_watchfd_position(&(info_array[use_idx])); if (position_now >= 0) { - state_array[use_idx].initial_offset = position_now; + state_array[use_idx].display.initial_offset = position_now; info_array[use_idx].position = position_now; } } @@ -482,15 +482,15 @@ void pv_watchpid_setname(pvstate_t state, pvwatchfd_t info) memset(info->display_name, 0, PV_SIZEOF_DISPLAY_NAME); path_length = strlen(info->file_fdpath); - cwd_length = strlen(state->cwd); + cwd_length = strlen(state->status.cwd); if (cwd_length > 0 && path_length > cwd_length) { - if (0 == strncmp(info->file_fdpath, state->cwd, cwd_length)) { + if (0 == strncmp(info->file_fdpath, state->status.cwd, cwd_length)) { file_fdpath += cwd_length + 1; path_length -= cwd_length + 1; } } - max_display_length = (state->width / 2) - 6; + max_display_length = (state->control.width / 2) - 6; if (max_display_length >= path_length) { (void) pv_snprintf(info->display_name, PV_SIZEOF_DISPLAY_NAME, "%4d:%.498s", info->watch_fd, file_fdpath);