1 /* 2 * Functions internal to the PV library. 3 */ 4 5 #ifndef _PV_INTERNAL_H 6 #define _PV_INTERNAL_H 1 7 8 #ifdef HAVE_CONFIG_H 9 #include "config.h" 10 #endif 11 12 #ifndef _PV_H 13 #include "pv.h" 14 #endif /* _PV_H */ 15 16 #include <signal.h> 17 #include <sys/types.h> 18 #include <sys/time.h> 19 #include <sys/stat.h> 20 21 #ifdef __cplusplus 22 extern "C" { 23 #endif 24 25 #define PV_DISPLAY_PROGRESS 1 26 #define PV_DISPLAY_TIMER 2 27 #define PV_DISPLAY_ETA 4 28 #define PV_DISPLAY_RATE 8 29 #define PV_DISPLAY_AVERAGERATE 16 30 #define PV_DISPLAY_BYTES 32 31 #define PV_DISPLAY_NAME 64 32 #define PV_DISPLAY_BUFPERCENT 128 33 #define PV_DISPLAY_OUTPUTBUF 256 34 #define PV_DISPLAY_FINETA 512 35 36 #define RATE_GRANULARITY 100000 /* usec between -L rate chunks */ 37 #define REMOTE_INTERVAL 100000 /* usec between checks for -R */ 38 #define BUFFER_SIZE 409600 /* default transfer buffer size */ 39 #define BUFFER_SIZE_MAX 524288 /* max auto transfer buffer size */ 40 #define MAX_READ_AT_ONCE 524288 /* max to read() in one go */ 41 #define MAX_WRITE_AT_ONCE 524288 /* max to write() in one go */ 42 #define TRANSFER_READ_TIMEOUT 90000 /* usec to time reads out at */ 43 #define TRANSFER_WRITE_TIMEOUT 900000 /* usec to time writes out at */ 44 45 #define MAXIMISE_BUFFER_FILL 1 46 47 48 /* 49 * Structure for holding PV internal state. Opaque outside the PV library. 50 */ 51 struct pvstate_s { 52 /*************** 53 * Input files * 54 ***************/ 55 int input_file_count; /* number of input files */ 56 const char **input_files; /* input files (0=first) */ 57 58 /******************* 59 * Program control * 60 *******************/ 61 bool force; /* display even if not on terminal */ 62 bool cursor; /* use cursor positioning */ 63 bool numeric; /* numeric output only */ 64 bool wait; /* wait for data before display */ 65 bool linemode; /* count lines instead of bytes */ 66 bool null; /* lines are null-terminated */ 67 bool no_op; /* do nothing other than pipe data */ 68 unsigned int skip_errors; /* skip read errors counter */ 69 bool stop_at_size; /* set if we stop at "size" bytes */ 70 bool no_splice; /* never use splice() */ 71 unsigned long long rate_limit; /* rate limit, in bytes per second */ 72 unsigned long long target_buffer_size; /* buffer size (0=default) */ 73 unsigned long long size; /* total size of data */ 74 double interval; /* interval between updates */ 75 double delay_start; /* delay before first display */ 76 unsigned int watch_pid; /* process to watch fds of */ 77 int watch_fd; /* fd to watch */ 78 unsigned int width; /* screen width */ 79 unsigned int height; /* screen height */ 80 const char *name; /* display name */ 81 char default_format[512]; /* default format string */ 82 const char *format_string; /* output format string */ 83 84 /****************** 85 * Program status * 86 ******************/ 87 const char *program_name; /* program name for error reporting */ 88 const char *current_file; /* current file being read */ 89 int exit_status; /* exit status to give (0=OK) */ 90 91 /******************* 92 * Signal handling * 93 *******************/ 94 int pv_sig_old_stderr; /* see pv_sig_ttou() */ 95 struct timeval pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */ 96 struct timeval pv_sig_toffset; /* total time spent stopped */ 97 volatile sig_atomic_t pv_sig_newsize; /* whether we need to get term size again */ 98 volatile sig_atomic_t pv_sig_abort; /* whether we need to abort right now */ 99 volatile sig_atomic_t reparse_display; /* whether to re-check format string */ 100 struct sigaction pv_sig_old_sigpipe; 101 struct sigaction pv_sig_old_sigttou; 102 struct sigaction pv_sig_old_sigtstp; 103 struct sigaction pv_sig_old_sigcont; 104 struct sigaction pv_sig_old_sigwinch; 105 struct sigaction pv_sig_old_sigint; 106 struct sigaction pv_sig_old_sighup; 107 struct sigaction pv_sig_old_sigterm; 108 109 /***************** 110 * Display state * 111 *****************/ 112 long percentage; 113 long double prev_elapsed_sec; 114 long double prev_rate; 115 long double prev_trans; 116 unsigned long long initial_offset; 117 char *display_buffer; 118 long display_buffer_size; 119 int lastoutput_length; /* number of last-output bytes to show */ 120 unsigned char lastoutput_buffer[256]; 121 int prev_width; /* screen width last time we were called */ 122 int prev_length; /* length of last string we output */ 123 char str_name[512]; 124 char str_transferred[128]; 125 char str_bufpercent[128]; 126 char str_timer[128]; 127 char str_rate[128]; 128 char str_average_rate[128]; 129 char str_progress[1024]; 130 char str_lastoutput[512]; 131 char str_eta[128]; 132 char str_fineta[128]; 133 unsigned long components_used; /* bitmask of components used */ 134 struct { 135 const char *string; 136 int length; 137 } format[100]; 138 bool display_visible; /* set once anything written to terminal */ 139 140 /******************** 141 * Cursor/IPC state * 142 ********************/ 143 #ifdef HAVE_IPC 144 int crs_shmid; /* ID of our shared memory segment */ 145 int crs_pvcount; /* number of `pv' processes in total */ 146 int crs_pvmax; /* highest number of `pv's seen */ 147 int *crs_y_top; /* pointer to Y coord of topmost `pv' */ 148 int crs_y_lastread; /* last value of _y_top seen */ 149 int crs_y_offset; /* our Y offset from this top position */ 150 int crs_needreinit; /* counter if we need to reinit cursor pos */ 151 bool crs_noipc; /* set if we can't use IPC */ 152 #endif /* HAVE_IPC */ 153 int crs_lock_fd; /* fd of lockfile, -1 if none open */ 154 char crs_lock_file[1024]; 155 int crs_y_start; /* our initial Y coordinate */ 156 157 /******************* 158 * Transfer state * 159 *******************/ 160 /* 161 * The transfer buffer is used for moving data from the input files 162 * to the output when splice() is not available. 163 * 164 * If buffer_size is smaller than pv__target_bufsize, then 165 * pv_transfer will try to reallocate transfer_buffer to make 166 * buffer_size equal to pv__target_bufsize. 167 * 168 * Data from the input files is read into the buffer; read_position 169 * is the offset in the buffer that we've read data up to. 170 * 171 * Data is written to the output from the buffer, and write_position 172 * is the offset in the buffer that we've written data up to. It 173 * will always be less than or equal to read_position. 174 */ 175 unsigned char *transfer_buffer; /* data transfer buffer */ 176 unsigned long long buffer_size; /* size of buffer */ 177 unsigned long read_position; /* amount of data in buffer */ 178 unsigned long write_position; /* buffered data written */ 179 180 /* 181 * While reading from a file descriptor we keep track of how many 182 * times in a row we've seen errors (read_errors_in_a_row), and 183 * whether or not we have put a warning on stderr about read errors 184 * on this fd (read_error_warning_shown). 185 * 186 * Whenever the active file descriptor changes from 187 * last_read_skip_fd, we reset read_errors_in_a_row and 188 * read_error_warning_shown to 0 for the new file descriptor and set 189 * last_read_skip_fd to the new fd number. 190 * 191 * This way, we're treating each input file separately. 192 */ 193 int last_read_skip_fd; 194 unsigned long read_errors_in_a_row; 195 int read_error_warning_shown; 196 #ifdef HAVE_SPLICE 197 /* 198 * These variables are used to keep track of whether splice() was 199 * used; splice_failed_fd is the file descriptor that splice() last 200 * failed on, so that we don't keep trying to use it on an fd that 201 * doesn't support it, and splice_used is set to 1 if splice() was 202 * used this time within pv_transfer(). 203 */ 204 int splice_failed_fd; 205 int splice_used; 206 #endif 207 long to_write; /* max to write this time around */ 208 long written; /* bytes sent to stdout this time */ 209 }; 210 211 212 struct pvwatchfd_s { 213 unsigned int watch_pid; /* PID to watch */ 214 int watch_fd; /* fd to watch, -1 = not displayed */ 215 char file_fdinfo[4096]; /* path to /proc fdinfo file */ 216 char file_fd[4096]; /* path to /proc fd symlink */ 217 char file_fdpath[4096]; /* path to file that was opened */ 218 char display_name[512]; /* name to show on progress bar */ 219 struct stat64 sb_fd; /* stat of fd symlink */ 220 struct stat64 sb_fd_link; /* lstat of fd symlink */ 221 unsigned long long size; /* size of whole file, 0 if unknown */ 222 long long position; /* position last seen at */ 223 struct timeval start_time; /* time we started watching the fd */ 224 }; 225 typedef struct pvwatchfd_s *pvwatchfd_t; 226 227 void pv_error(pvstate_t, char *, ...); 228 229 int pv_main_loop(pvstate_t); 230 void pv_display(pvstate_t, long double, long long, long long); 231 long pv_transfer(pvstate_t, int, int *, int *, unsigned long long, long *); 232 void pv_set_buffer_size(unsigned long long, int); 233 int pv_next_file(pvstate_t, int, int); 234 235 void pv_crs_fini(pvstate_t); 236 void pv_crs_init(pvstate_t); 237 void pv_crs_update(pvstate_t, char *); 238 #ifdef HAVE_IPC 239 void pv_crs_needreinit(pvstate_t); 240 #endif 241 242 void pv_sig_allowpause(void); 243 void pv_sig_checkbg(void); 244 void pv_sig_nopause(void); 245 246 void pv_remote_init(pvstate_t); 247 void pv_remote_check(pvstate_t); 248 void pv_remote_fini(pvstate_t); 249 int pv_remote_set(pvstate_t); 250 251 int pv_watchfd_info(pvstate_t, pvwatchfd_t, int); 252 int pv_watchfd_changed(pvwatchfd_t); 253 long long pv_watchfd_position(pvwatchfd_t); 254 int pv_watchpid_scanfds(pvstate_t, pvstate_t, unsigned int, int *, pvwatchfd_t *, pvstate_t *, int *); 255 void pv_watchpid_setname(pvstate_t, pvwatchfd_t); 256 257 #ifdef __cplusplus 258 } 259 #endif 260 261 #endif /* _PV_INTERNAL_H */ 262 263 /* EOF */ 264