+ return 1;
+}
+
+static void
+get_stats(const char *file, struct statinfo *info, int *opt, int other_opt,
+ int is_srv)
+{
+ FILE *fp;
+ char buf[10];
+ int err = 1;
+ char *label = is_srv ? "Server" : "Client";
+
+ /* try to guess what type of stat file we're dealing with */
+ if ((fp = fopen(file, "r")) == NULL)
+ goto out;
+ if (fgets(buf, 10, fp) == NULL)
+ goto out;
+ if (!strncmp(buf, "net ", 4)) {
+ /* looks like raw client stats */
+ if (is_srv) {
+ fprintf(stderr, "Warning: no server info present in "
+ "raw client stats file.\n");
+ *opt = 0;
+ } else
+ err = parse_raw_statfile(file, info);
+ } else if (!strncmp(buf, "rc ", 3)) {
+ /* looks like raw server stats */
+ if (!is_srv) {
+ fprintf(stderr, "Warning: no client info present in "
+ "raw server stats file.\n");
+ *opt = 0;
+ } else
+ err = parse_raw_statfile(file, info);
+ } else
+ /* looks like pretty client and server stats */
+ err = parse_pretty_statfile(file, info);
+out:
+ if (fp)
+ fclose(fp);
+ if (err) {
+ if (!other_opt) {
+ fprintf(stderr, "Error: No %s Stats (%s: %m). \n",
+ label, file);
+ exit(2);
+ }
+ *opt = 0;
+ }
+}
+
+/*
+ * This is for proc2/3/4-type stats, where, in the /proc files, the first entry's value
+ * denotes the number of subsequent entries. statinfo value arrays contain an additional
+ * field at the end which contains the sum of all previous elements in the array -- so,
+ * there are stats if the sum's greater than the entry-count.
+ */
+static int
+has_stats(const unsigned int *info, int nr)
+{
+ return (info[0] && info[nr-1] > info[0]);
+}
+static int
+has_rpcstats(const unsigned int *info, int size)
+{
+ int i, cnt;
+
+ for (i=0, cnt=0; i < size; i++)
+ cnt += info[i];
+ return cnt;
+}
+
+/*
+ * take the difference of each individual stat value in 'new' and 'old'
+ * and store the results back into 'new'
+ */
+static void
+diff_stats(struct statinfo *new, struct statinfo *old, int is_srv)
+{
+ int i, j, nodiff_first_index, should_diff;
+
+ /*
+ * Different stat types have different formats in the /proc
+ * files: for the proc2/3/4-type stats, the first entry has
+ * the total number of subsequent entries; one does not want
+ * to diff that first entry. The other stat types aren't like
+ * this. So, we diff a given entry if it's not of one of the
+ * procX types ("i" < 2 for clt, < 4 for srv), or if it's not
+ * the first entry ("j" > 0).
+ */
+ nodiff_first_index = 2 + (2 * is_srv);
+
+ for (i = 0; old[i].tag; i++) {
+ for (j = 0; j < new[i].nrvals; j++) {
+ should_diff = (i < nodiff_first_index || j > 0);
+ if (should_diff)
+ new[i].valptr[j] -= old[i].valptr[j];
+ }
+
+ /*
+ * Make sure that the "totals" entry (last value in
+ * each stat array) for the procX-type stats has the
+ * "numentries" entry's (first value in procX-type
+ * stat arrays) constant value added-back after the
+ * diff -- i.e., it should always be included in the
+ * total.
+ */
+ if (!strncmp("proc", new[i].tag, 4) && old[i].valptr[0])
+ new[i].valptr[new[i].nrvals - 1] += new[i].valptr[0];
+ }
+}
+
+static void
+unpause(int sig)
+{
+ double time_diff;
+ int minutes, seconds;
+ time_t endtime;
+
+ endtime = time(NULL);
+ time_diff = difftime(endtime, starttime);
+ minutes = time_diff / 60;
+ seconds = (int)time_diff % 60;
+ printf("Signal %d received; displaying (only) statistics gathered over the last %d minutes, %d seconds:\n\n", sig, minutes, seconds);
+}
+
+static void
+update_old_counters(struct statinfo *new, struct statinfo *old)
+{
+ int z, i;
+ for (z = 0; old[z].tag; z++)
+ for (i = 0; i <= old[z].nrvals; i++)
+ old[z].valptr[i] += new[z].valptr[i];
+