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