#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <mach/mach.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sadc.h>
#include <sar.h>
#define IFNET_32_BIT_COUNTERS 1
int t_interval = 5;
char * t_intervalp = "5";
int n_samples = 1;
char * n_samplesp = "1";
char *outfile = NULL;
int ofd = 0;
int ifd = 0;
char *infile = NULL;
pid_t pid;
int fd[2];
char *optionstring1 = "Adgn:puo:";
char *optionstring1_usage = "/usr/bin/sar [-Adgpu] [-n { DEV | EDEV | PPP } ] [-o filename] t [n]";
char *optionstring2 = "Adgn:pue:f:i:s:";
char *optionstring2_usage = "/usr/bin/sar [-Adgpu] [-n { DEV | EDEV | PPP }] [-e time] [-f filename] [-i sec] [-s time]";
int aflag = 0;
int Aflag = 0;
int bflag = 0;
int cflag = 0;
int dflag = 0;
int gflag = 0;
int kflag = 0;
int mflag = 0;
int nflag = 0;
int network_mode = 0;
char *sadc_mflagp = "-m";
char *sadc_ppp_modep = "PPP";
int pflag = 0;
int qflag = 0;
int rflag = 0;
int uflag = 0;
int vflag = 0;
int wflag = 0;
int yflag = 0;
int set_default_flag = 1;
int flag_count = 0;
#define HOURS_PER_DAY 24
#define MINS_PER_HOUR 60
#define SECS_PER_MIN 60
#define SECS_PER_DAY (SECS_PER_MIN * MINS_PER_HOUR * HOURS_PER_DAY)
time_t end_time = 0;
int iflag = 0;
int iseconds = 0;
time_t start_time = 0;
int oflag = 0;
int fflag = 0;
struct vm_statistics prev_vmstat, avg_vmstat, cur_vmstat;
host_cpu_load_info_data_t prev_cpuload, avg_cpuload, cur_cpuload;
struct drivestats_report *dr_head = NULL;
struct drivepath *dp_table = NULL;
int dp_count = 0;
struct netstats_report *nr_table = NULL;
int nr_count;
struct netstats *netstat_readbuf = NULL;
size_t netstat_readbuf_size = 0;
int avg_counter = 0;
int avg_interval = 0;
extern int errno;
static void exit_usage();
static void open_output_file(char *path);
static void open_input_file(char *path);
static void read_record_hdr(struct record_hdr *hdr, int writeflag);
static void read_record_data(char *buf, size_t size, int writeflag);
static void write_record_hdr(struct record_hdr *hdr);
static void write_record_data(char *buf, size_t size);
static long convert_hms(char *string);
static char *get_hms_string(time_t, char *);
static int find_restart_header(struct record_hdr *);
static void print_all_column_headings (time_t timestamp);
static void print_column_heading (int type, char *timebufptr, int mode);
static void read_sample_set(int, time_t, struct record_hdr *);
static void do_main_workloop();
static int bypass_sample_set(struct record_hdr *, time_t);
static void skip_data(int);
static int get_cpu_sample(int flag, struct record_hdr *hdr);
static void print_cpu_sample(char *timebufptr);
static int get_vmstat_sample(int flag, struct record_hdr *hdr);
static void print_vmstat_sample(char *timebufptr);
static int get_drivestats_sample(int flag, struct record_hdr *hdr);
static void init_drivestats(struct drivestats_report *dr);
static void print_drivestats_sample(char *timebufptr);
static int get_drivepath_sample(int flag, struct record_hdr *hdr);
static void set_cur_netstats(struct netstats_report *nr, struct netstats *ns);
static void init_prev_netstats(struct netstats_report *nr);
static int get_netstats_sample(int flag, struct record_hdr *hdr);
static void print_netstats_sample(char *timebufptr);
static void exit_average();
int
main(argc, argv)
int argc;
char *argv[];
{
char ch;
time_t curr_time;
char timebuf[26];
char filenamebuf[20];
char *optstring = NULL;
int optstringval;
int i;
optreset=0;
optstringval=0;
while((ch=getopt(argc, argv, "aAbcdgkmn:pqruvwyo:e:f:i:s:")) != EOF) {
switch(ch) {
case 'o':
if (optstringval == 2)
exit_usage();
optstring=optionstring1;
optstringval=1;
break;
case 'e':
case 'f':
case 'i':
case 's':
if (optstringval == 1)
exit_usage();
optstring=optionstring2;
optstringval=2;
break;
default:
break;
}
}
if (!optstring)
{
if (argc - optind > 0)
{
optstring=optionstring1;
optstringval=1;
}
else
{
optstring=optionstring2;
optstringval=2;
}
}
optreset = optind = 1;
while ((ch=getopt(argc, argv, optstring)) != EOF) {
switch (ch) {
case 'a':
aflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'A':
Aflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'b':
bflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'c':
cflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'd':
dflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'g':
gflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'k':
kflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'm':
mflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'n':
nflag= 1;
if (!strncmp(optarg, "PPP", 3))
network_mode |= NET_PPP_MODE;
else if (!strncmp(optarg, "DEV", 3))
network_mode |= NET_DEV_MODE;
else if (!strncmp(optarg, "EDEV", 4))
network_mode |= NET_EDEV_MODE;
else
exit_usage();
set_default_flag = 0;
flag_count++;
break;
case 'p':
pflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'q':
qflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'r':
rflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'u':
uflag= 1;
set_default_flag = 0;
flag_count++;
break;
case 'v':
vflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'w':
wflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'y':
yflag = 1;
set_default_flag = 0;
flag_count++;
break;
case 'o':
oflag = 1;
outfile=optarg;
(void)open_output_file(outfile);
break;
case 'e':
end_time = convert_hms(optarg);
break;
case 'f':
fflag = 1;
infile=optarg;
break;
case 'i':
iflag = 1;
iseconds=atoi(optarg);
break;
case 's':
start_time = convert_hms(optarg);
break;
default:
exit_usage();
break;
}
}
if (Aflag)
{
dflag = gflag = pflag = uflag = 1;
if (!nflag)
{
nflag = 1;
network_mode = NET_DEV_MODE | NET_EDEV_MODE;;
}
flag_count = 2;
}
else if (set_default_flag)
{
uflag=1;
flag_count++;
}
if (nflag)
{
if (network_mode & NET_PPP_MODE)
{
if (!(network_mode & NET_DEV_MODE) &&
!(network_mode & NET_EDEV_MODE))
{
network_mode |= NET_DEV_MODE;
network_mode |= NET_EDEV_MODE;
flag_count++;
}
}
}
argc -= optind;
argv += optind;
signal(SIGINT, exit_average);
signal(SIGQUIT, exit_average);
signal(SIGHUP, exit_average);
signal(SIGTERM, exit_average);
if (optstringval == 1)
{
char *p;
if (argc >= 1)
{
errno = 0;
t_interval = strtol(argv[0], &p, 0);
t_intervalp = argv[0];
if (errno || (*p != '\0') || t_interval <= 0 )
exit_usage();
if (argc >= 2)
{
errno=0;
n_samples = strtol(argv[1], &p, 0);
n_samplesp = argv[1];
if (errno || (*p != '\0') || n_samples <= 0)
exit_usage();
}
}
}
if (fflag)
{
(void)open_input_file(infile);
}
else if (optstringval == 2)
{
curr_time = time((time_t *)0);
ctime_r(&curr_time, timebuf);
strncpy(filenamebuf, "/var/log/sa/sa", 14);
strncpy(&filenamebuf[14], &timebuf[8], 2);
if (filenamebuf[14] == ' ')
filenamebuf[14] = '0';
filenamebuf[16]='\0';
infile = filenamebuf;
(void)open_input_file(infile);
}
else if (optstringval == 1)
{
if (pipe(fd) == -1)
{
fprintf(stderr, "sar: pipe(2) failed, errno = (%d)\n",errno);
exit(1);
}
if ((pid=fork()) == 0)
{
#if 0
int efd;
#endif
int fdlimit = getdtablesize();
for (i=0; i < fdlimit; i++) {
if ((i != fd[0]) && (i != fd[1]))
(void)close(i);
}
#if 0
efd = open("/tmp/errlog", O_CREAT|O_APPEND|O_RDWR, 0666);
if (dup2(efd,2) == -1) {
exit(1);
}
#endif
if (dup2(fd[0],0) == -1) {
exit(1);
}
if (dup2(fd[1],1) == -1) {
exit(1);
}
if (network_mode & NET_PPP_MODE)
execl("/usr/lib/sa/sadc", "sadc", sadc_mflagp, sadc_ppp_modep, t_intervalp, n_samplesp, NULL);
else
execl("/usr/lib/sa/sadc", "sadc", t_intervalp, n_samplesp, NULL);
perror("execlp sadc");
exit(2);
}
else
{
if (pid == -1) {
fprintf(stderr, "sar: fork(2) failed, errno = (%d)\n",errno);
exit(1);
}
close (fd[1]);
ifd = fd[0];
}
}
else
{
fprintf(stderr, "sar: no input file recognized\n");
exit_usage();
}
(void)do_main_workloop();
(void)exit_average();
exit(0);
}
static void
exit_usage()
{
fprintf(stderr, "\n%s\n\n", optionstring1_usage);
fprintf(stderr, "%s\n", optionstring2_usage);
exit(EXIT_FAILURE);
}
static void
open_output_file(char *path)
{
if ((ofd = open(path, O_CREAT|O_APPEND|O_TRUNC|O_WRONLY, 0664)) == -1 )
{
fprintf(stderr, "sar: failed to open output file [%s]\n", path);
exit_usage();
}
}
static void
open_input_file(char *path)
{
if ((ifd = open(path, O_RDONLY, 0)) == -1)
{
fprintf(stderr, "sar: failed to open input file [%d][%s]\n", ifd, path);
exit_usage();
}
}
static void
read_record_hdr(hdr, writeflag)
struct record_hdr *hdr;
int writeflag;
{
errno = 0;
int num = 0;
int n = 0;
size_t size = 0;
size = sizeof(struct record_hdr);
while (size)
{
num = read(ifd, &hdr[n], size);
if (num > 0)
{
n += num;
size -= num;
}
else if (num == 0)
exit_average();
else
{
fprintf(stderr, "sar: read_record_data failed, errno=%d num=%d, size=%d\n", (int)errno, (int)num, (int)size);
exit(EXIT_FAILURE);
}
}
if (oflag && writeflag)
write_record_hdr(hdr);
return;
}
static void
read_record_data(buf, size, writeflag)
char * buf;
size_t size;
int writeflag;
{
errno = 0;
size_t num = 0;
size_t n = 0;
while (size)
{
num = read(ifd, &buf[n], size);
if (num > 0)
{
n += num;
size -= num;
}
else if (num == 0)
exit_average();
else
{
fprintf(stderr, "sar: read_record_data failed, errno=%d num=%d, size=%d\n", (int)errno, (int)num, (int)size);
exit(EXIT_FAILURE);
}
}
if (oflag && writeflag)
write_record_data(buf, n);
return;
}
static void
write_record_hdr(hdr)
struct record_hdr *hdr;
{
errno = 0;
int num;
if ((num = write(ofd, hdr, sizeof(struct record_hdr))) == -1)
{
fprintf(stderr, "sar: write_record_hdr failed, errno=%d\n", errno);
exit(EXIT_FAILURE);
}
return;
}
static void
write_record_data(char *buf, size_t nbytes)
{
errno = 0;
int num;
if ((num = write(ofd, buf, nbytes)) == -1)
{
fprintf(stderr, "sar: write_record_data failed, errno=%d\n", errno);
exit(EXIT_FAILURE);
}
return;
}
static time_t
convert_hms(string)
char *string;
{
int hh = 0;
int mm = 0;
int ss = 0;
time_t seconds;
time_t timestamp;
struct tm *tm;
int i;
if (string == NULL || *string == '\0')
goto convert_err;
for (i=0; string[i] != '\0'; i++)
{
if ((!isdigit(string[i])) && (string[i] != ':'))
{
goto convert_err;
}
}
if (sscanf(string, "%d:%d:%d", &hh, &mm, &ss) != 3)
{
if (sscanf(string, "%d:%d", &hh, &mm) != 2)
{
if (sscanf(string, "%d", &hh) != 1)
{
goto convert_err;
}
}
}
if (hh < 0 || hh >= HOURS_PER_DAY ||
mm < 0 || mm >= MINS_PER_HOUR ||
ss < 0 || ss > SECS_PER_MIN)
{
goto convert_err;
}
seconds = ((((hh * MINS_PER_HOUR) + mm) * SECS_PER_MIN) + ss);
timestamp = time((time_t *)0);
tm=localtime(×tamp);
seconds -= tm->tm_gmtoff;
return(seconds);
convert_err:
fprintf(stderr, "sar: time format usage is hh[:mm[:ss]]\n");
exit_usage();
return(0);
}
static char *
get_hms_string(tdata, tbuf)
time_t tdata;
char *tbuf;
{
time_t t;
char *p;
t = tdata;
ctime_r(&t, tbuf);
p=&tbuf[11];
tbuf[19] = 0;
return(p);
}
#define INIT_SET 0
#define PRINT_SET 1
#define PRINT_AVG 2
static void
do_main_workloop()
{
struct record_hdr hdr;
time_t cur_timestamp = 0;
time_t next_timestamp = 0;
if (!find_restart_header(&hdr))
exit(1);
cur_timestamp = hdr.rec_timestamp;
if (start_time < (cur_timestamp % SECS_PER_DAY))
start_time = cur_timestamp;
else
start_time += cur_timestamp - (cur_timestamp % SECS_PER_DAY);
if (end_time != 0)
end_time += cur_timestamp - (cur_timestamp % SECS_PER_DAY);
#if 0
fprintf(stderr, "start = %ld, end = %ld, cur=%ld, [24hour - %ld]\n",
start_time, end_time, cur_timestamp,(cur_timestamp % SECS_PER_DAY));
#endif
while (cur_timestamp < start_time)
{
bypass_sample_set(&hdr, cur_timestamp);
cur_timestamp = hdr.rec_timestamp;
}
next_timestamp = cur_timestamp + iseconds;
print_all_column_headings(cur_timestamp);
read_sample_set(INIT_SET, cur_timestamp, &hdr);
cur_timestamp = hdr.rec_timestamp;
while ((end_time == 0) || (next_timestamp < end_time))
{
if (cur_timestamp < next_timestamp)
{
bypass_sample_set (&hdr, cur_timestamp);
cur_timestamp = hdr.rec_timestamp;
}
else
{
if (avg_interval == 0)
{
if (iseconds)
avg_interval = iseconds;
else
avg_interval = cur_timestamp - next_timestamp;
}
next_timestamp = cur_timestamp + iseconds;
read_sample_set(PRINT_SET, cur_timestamp, &hdr);
cur_timestamp = hdr.rec_timestamp;
}
}
exit_average();
}
static int
find_restart_header (ret_hdr)
struct record_hdr *ret_hdr;
{
struct record_hdr hdr;
int bufsize = 0;
char *buf = NULL;
errno = 0;
restart_loop:
read_record_hdr(&hdr, FALSE);
if (hdr.rec_type == SAR_RESTART)
{
*ret_hdr = hdr;
if (oflag)
write_record_hdr(&hdr);
if (buf)
free(buf);
return(1);
}
if (hdr.rec_count)
{
if (fflag)
{
if ((lseek(ifd, (hdr.rec_count * hdr.rec_size), SEEK_CUR)) == -1)
{
fprintf(stderr, "sar: lseek failed, errno=%d\n", errno);
exit(EXIT_FAILURE);
}
}
else
{
if (bufsize < (hdr.rec_count * hdr.rec_size))
{
if (buf)
free(buf);
bufsize = hdr.rec_count * hdr.rec_size;
if((buf = (char *)malloc(bufsize)) == NULL)
{
fprintf(stderr, "sar: malloc failed\n");
return(0);
}
}
read_record_data(buf, (hdr.rec_count * hdr.rec_size), FALSE);
}
}
goto restart_loop;
}
static void
print_all_column_headings(timestamp)
time_t timestamp;
{
char timebuf[26];
char *timebufp;
timebufp = get_hms_string (timestamp, timebuf);
if (uflag)
print_column_heading(SAR_CPU, timebufp, 0);
if (gflag)
print_column_heading(SAR_VMSTAT, timebufp, 0);
if (pflag )
print_column_heading(SAR_VMSTAT, timebufp, 1);
if (dflag)
print_column_heading(SAR_DRIVESTATS, timebufp, 0);
if (nflag)
{
if (network_mode & NET_DEV_MODE)
print_column_heading(SAR_NETSTATS, timebufp, NET_DEV_MODE);
if (network_mode & NET_EDEV_MODE)
print_column_heading(SAR_NETSTATS, timebufp, NET_EDEV_MODE);
}
}
static int
bypass_sample_set (ret_hdr, timestamp)
struct record_hdr *ret_hdr;
time_t timestamp;
{
struct record_hdr hdr;
int bufsize = 0;
char *buf = NULL;
bypass_loop:
read_record_hdr(&hdr, TRUE);
if (hdr.rec_type == SAR_TIMESTAMP)
{
*ret_hdr = hdr;
if (buf)
free(buf);
return(1);
}
if (hdr.rec_count)
{
if (fflag && !oflag)
{
errno = 0;
if ((lseek(ifd, (hdr.rec_count * hdr.rec_size), SEEK_CUR)) == -1)
{
fprintf(stderr, "sar: lseek failed, errno=%d\n", errno);
exit(EXIT_FAILURE);
}
}
else
{
if (bufsize < (hdr.rec_count * hdr.rec_size))
{
if (buf)
free(buf);
bufsize = hdr.rec_count * hdr.rec_size;
if((buf = (char *)malloc(bufsize)) == NULL)
{
fprintf(stderr, "sar: malloc failed\n");
exit(EXIT_FAILURE);
}
}
read_record_data(buf, (hdr.rec_count * hdr.rec_size), TRUE);
}
}
goto bypass_loop;
}
static void
read_sample_set(flag, timestamp, ret_hdr)
int flag;
time_t timestamp;
struct record_hdr *ret_hdr;
{
struct record_hdr hdr;
char timebuf[26];
char *timebufp;
char *indent_string;
char *indent_string_wide;
char *indent_string_narrow;
int sar_cpu = 0;
int sar_vmstat=0;
int sar_drivestats=0;
int sar_drivepath=0;
int sar_netstats = 0;
indent_string_wide = " ";
indent_string_narrow = " ";
indent_string = indent_string_narrow;
read_record_hdr(&hdr, TRUE);
while (hdr.rec_type != SAR_TIMESTAMP)
{
switch (hdr.rec_type)
{
case SAR_CPU:
sar_cpu = get_cpu_sample(flag, &hdr);
break;
case SAR_VMSTAT:
sar_vmstat=get_vmstat_sample(flag, &hdr);
break;
case SAR_DRIVEPATH:
sar_drivepath = get_drivepath_sample(flag, &hdr);
if (sar_drivepath < 0)
fprintf(stderr, "sar: drivepath sync code error %d\n", sar_drivepath);
break;
case SAR_DRIVESTATS:
sar_drivestats = get_drivestats_sample(flag, &hdr);
break;
case SAR_NETSTATS:
sar_netstats = get_netstats_sample(flag, &hdr);
break;
default:
break;
}
read_record_hdr(&hdr, TRUE);
}
*ret_hdr = hdr;
if (flag == PRINT_SET)
{
avg_counter++;
timebufp = get_hms_string(timestamp, timebuf);
if (uflag && sar_cpu)
print_cpu_sample(timebufp);
if((gflag || pflag) && sar_vmstat)
print_vmstat_sample(timebufp);
if (dflag && sar_drivestats)
print_drivestats_sample(timebufp);
if (nflag && sar_netstats)
print_netstats_sample(timebufp);
}
}
static void
skip_data(bufsize)
int bufsize;
{
char *buf = NULL;
if (fflag)
{
if ((lseek(ifd, bufsize, SEEK_CUR) == -1))
{
fprintf(stderr, "sar: lseek failed, errno=%d\n", errno);
exit(EXIT_FAILURE);
}
}
else
{
if((buf = (char *)malloc(bufsize)) == NULL)
{
fprintf(stderr, "sar: malloc failed\n");
exit(EXIT_FAILURE);
}
read_record_data(buf, bufsize, TRUE);
}
if (buf)
free(buf);
return;
}
static int
get_cpu_sample(flag, hdr)
int flag;
struct record_hdr *hdr;
{
int datasize;
datasize = hdr->rec_count * hdr->rec_size;
if (datasize != sizeof(host_cpu_load_info_data_t))
{
skip_data(datasize);
return(0);
}
read_record_data ((char *)&cur_cpuload, (int)sizeof(host_cpu_load_info_data_t), TRUE );
if (flag == INIT_SET)
{
prev_cpuload = cur_cpuload;
bzero(&avg_cpuload, sizeof(avg_cpuload));
}
return(1);
}
static void
print_cpu_sample(timebufptr)
char * timebufptr;
{
double time;
time = 0.0;
cur_cpuload.cpu_ticks[CPU_STATE_USER]
-= prev_cpuload.cpu_ticks[CPU_STATE_USER];
prev_cpuload.cpu_ticks[CPU_STATE_USER]
+= cur_cpuload.cpu_ticks[CPU_STATE_USER];
time += cur_cpuload.cpu_ticks[CPU_STATE_USER];
cur_cpuload.cpu_ticks[CPU_STATE_NICE]
-= prev_cpuload.cpu_ticks[CPU_STATE_NICE];
prev_cpuload.cpu_ticks[CPU_STATE_NICE]
+= cur_cpuload.cpu_ticks[CPU_STATE_NICE];
time += cur_cpuload.cpu_ticks[CPU_STATE_NICE];
cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
-= prev_cpuload.cpu_ticks[CPU_STATE_SYSTEM];
prev_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
+= cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM];
time += cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM];
cur_cpuload.cpu_ticks[CPU_STATE_IDLE]
-= prev_cpuload.cpu_ticks[CPU_STATE_IDLE];
prev_cpuload.cpu_ticks[CPU_STATE_IDLE]
+= cur_cpuload.cpu_ticks[CPU_STATE_IDLE];
time += cur_cpuload.cpu_ticks[CPU_STATE_IDLE];
avg_cpuload.cpu_ticks[CPU_STATE_USER] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_USER]
/ (time ? time : 1));
avg_cpuload.cpu_ticks[CPU_STATE_NICE] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_NICE]
/ (time ? time : 1));
avg_cpuload.cpu_ticks[CPU_STATE_SYSTEM] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
/ (time ? time : 1));
avg_cpuload.cpu_ticks[CPU_STATE_IDLE] += rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_IDLE]
/ (time ? time : 1));
if(flag_count > 1)
print_column_heading(SAR_CPU, timebufptr, 0);
fprintf(stdout, "%s%5.0f ", timebufptr,
rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_USER]
/ (time ? time : 1)));
fprintf(stdout, "%4.0f ",
rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_NICE]
/ (time ? time : 1)));
fprintf(stdout, "%4.0f ",
rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
/ (time ? time : 1)));
fprintf(stdout, "%4.0f\n",
rint(100. * cur_cpuload.cpu_ticks[CPU_STATE_IDLE]
/ (time ? time : 1)));
}
static int
get_vmstat_sample(flag, hdr)
int flag;
struct record_hdr *hdr;
{
int datasize;
datasize = hdr->rec_count * hdr->rec_size;
if (datasize != sizeof(struct vm_statistics))
{
skip_data(datasize);
return(0);
}
read_record_data ((char *)&cur_vmstat, (int)sizeof(struct vm_statistics), TRUE );
if (flag == INIT_SET)
{
prev_vmstat = cur_vmstat;
bzero(&avg_vmstat, sizeof(avg_vmstat));
}
return(1);
}
static void
print_vmstat_sample(char *timebufptr)
{
cur_vmstat.faults -= prev_vmstat.faults;
prev_vmstat.faults += cur_vmstat.faults;
avg_vmstat.faults += cur_vmstat.faults;
cur_vmstat.cow_faults -= prev_vmstat.cow_faults;
prev_vmstat.cow_faults += cur_vmstat.cow_faults;
avg_vmstat.cow_faults += cur_vmstat.cow_faults;
cur_vmstat.zero_fill_count -= prev_vmstat.zero_fill_count;
prev_vmstat.zero_fill_count += cur_vmstat.zero_fill_count;
avg_vmstat.zero_fill_count += cur_vmstat.zero_fill_count;
cur_vmstat.reactivations -= prev_vmstat.reactivations;
prev_vmstat.reactivations += cur_vmstat.reactivations;
avg_vmstat.reactivations += cur_vmstat.reactivations;
cur_vmstat.pageins -= prev_vmstat.pageins;
prev_vmstat.pageins += cur_vmstat.pageins;
avg_vmstat.pageins += cur_vmstat.pageins;
cur_vmstat.pageouts -= prev_vmstat.pageouts;
prev_vmstat.pageouts += cur_vmstat.pageouts;
avg_vmstat.pageouts += cur_vmstat.pageouts;
if (gflag)
{
if (flag_count > 1)
print_column_heading(SAR_VMSTAT, timebufptr, 0);
fprintf(stdout, "%s %8.1f \n", timebufptr, (float)((float)cur_vmstat.pageouts/avg_interval));
}
if (pflag)
{
if (flag_count > 1)
print_column_heading(SAR_VMSTAT, timebufptr, 1);
fprintf(stdout, "%s %8.1f %8.1f %8.1f\n", timebufptr,
(float)((float)cur_vmstat.pageins / avg_interval),
(float)((float)cur_vmstat.cow_faults/avg_interval),
(float)((float)cur_vmstat.faults/avg_interval));
}
fflush(stdout);
}
static int
get_drivestats_sample(flag, hdr)
int flag;
struct record_hdr *hdr;
{
struct drivestats *databuf;
struct drivestats_report *dr;
size_t datasize;
int datacount;
int index;
int i;
datasize = hdr->rec_count * hdr->rec_size;
datacount = hdr->rec_count;
if (hdr->rec_size != sizeof(struct drivestats))
{
skip_data(datasize);
return(0);
}
if ((databuf = (struct drivestats *)malloc(datasize)) == NULL)
{
fprintf(stderr, "sar: malloc failed\n");
exit (EXIT_FAILURE);
}
bzero(databuf, datasize);
read_record_data ((char *)databuf, datasize, TRUE );
for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next)
{
dr->present = 0;
dr->cur_Reads = 0;
dr->cur_BytesRead = 0;
dr->cur_Writes = 0;
dr->cur_BytesWritten = 0;
dr->cur_LatentReadTime = 0;
dr->cur_LatentWriteTime = 0;
dr->cur_ReadErrors = 0;
dr->cur_WriteErrors = 0;
dr->cur_ReadRetries = 0;
dr->cur_WriteRetries = 0;
dr->cur_TotalReadTime = 0;
dr->cur_TotalWriteTime=0;
}
for (i=0; i< datacount; i++)
{
struct drivestats_report *dr_last = NULL;
index = databuf[i].drivepath_id;
for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next)
{
dr_last = dr;
if(index == dr->drivepath_id)
break;
}
if (dr == NULL)
{
if((dr = (struct drivestats_report *)malloc(sizeof(struct drivestats_report))) == NULL)
{
fprintf(stderr, "sar: malloc error\n");
exit(EXIT_FAILURE);
}
bzero((char *)dr, sizeof(struct drivestats_report));
dr->blocksize = databuf[i].blocksize;
dr->drivepath_id = index;
dr->next = NULL;
dr->avg_count = 0;
if ((index < dp_count) && (dp_table[index].state != DPSTATE_UNINITIALIZED))
strncpy(dr->name, dp_table[index].BSDName, MAXDRIVENAME+1);
else
strcpy(dr->name, "disk??");
if (dr_head == NULL)
{
dr_head = dr;
dr_head->next = NULL;
}
else
{
dr_last->next = (char *)dr;
}
}
dr->present = TRUE;
dr->cur_Reads = databuf[i].Reads;
dr->cur_BytesRead = databuf[i].BytesRead;
dr->cur_Writes = databuf[i].Writes;
dr->cur_BytesWritten = databuf[i].BytesWritten;
dr->cur_LatentReadTime = databuf[i].LatentReadTime;
dr->cur_LatentWriteTime = databuf[i].LatentWriteTime;
dr->cur_ReadErrors = databuf[i].ReadErrors;
dr->cur_WriteErrors = databuf[i].WriteErrors;
dr->cur_ReadRetries = databuf[i].ReadRetries;
dr->cur_WriteRetries = databuf[i].WriteRetries;
dr->cur_TotalReadTime = databuf[i].TotalReadTime;
dr->cur_TotalWriteTime=databuf[i].TotalWriteTime;
}
for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next)
{
if (dr->drivepath_id >= dp_count)
{
continue;
}
else
{
index = dr->drivepath_id;
}
if ((flag == INIT_SET) ||
(dp_table[index].state == DPSTATE_NEW) ||
(dp_table[index].state == DPSTATE_CHANGED) ||
(!dr->present))
{
if (dr->present)
dp_table[index].state = DPSTATE_ACTIVE;
init_drivestats(dr);
}
}
return(1);
}
static void
init_drivestats(struct drivestats_report *dr)
{
dr->avg_count = 0;
dr->prev_Reads = dr->cur_Reads;
dr->avg_Reads = 0;
dr->prev_BytesRead = dr->cur_BytesRead;
dr->avg_BytesRead = 0;
dr->prev_Writes = dr->cur_Writes;
dr->avg_Writes = 0;
dr->prev_BytesWritten = dr->cur_BytesWritten;
dr->avg_BytesWritten = 0;
dr->prev_LatentReadTime = dr->cur_LatentReadTime;
dr->avg_LatentReadTime = 0;
dr->prev_LatentWriteTime = dr->cur_LatentWriteTime ;
dr->avg_LatentWriteTime = 0;
dr->prev_ReadErrors = dr->cur_ReadErrors ;
dr->avg_ReadErrors = 0;
dr->prev_WriteErrors = dr->cur_WriteErrors ;
dr->avg_WriteErrors = 0;
dr->prev_ReadRetries = dr->cur_ReadRetries ;
dr->avg_ReadRetries = 0;
dr->prev_WriteRetries = dr->cur_WriteRetries ;
dr->avg_WriteRetries = 0;
dr->prev_TotalReadTime = dr->cur_TotalReadTime ;
dr->avg_TotalReadTime = 0;
dr->prev_TotalWriteTime = dr->cur_TotalWriteTime ;
dr->avg_TotalWriteTime = 0;
}
static void
print_drivestats_sample(char *timebufptr)
{
struct drivestats_report *dr;
long double transfers_per_second;
long double kb_per_transfer, mb_per_second;
u_int64_t interval_bytes, interval_transfers, interval_blocks;
u_int64_t interval_time;
long double blocks_per_second, ms_per_transaction;
if (flag_count > 1)
print_column_heading(SAR_DRIVESTATS, timebufptr, 0);
for (dr=dr_head; dr; dr=(struct drivestats_report *)dr->next)
{
if(!dr->present)
continue;
if ((dr->cur_Reads < dr->prev_Reads) ||
(dr->cur_BytesRead < dr->prev_BytesRead) ||
(dr->cur_Writes < dr->prev_Writes) ||
(dr->cur_BytesWritten < dr->prev_BytesWritten))
{
init_drivestats(dr);
continue;
}
dr->avg_count++;
dr->cur_Reads -= dr->prev_Reads;
dr->prev_Reads += dr->cur_Reads;
dr->avg_Reads += dr->cur_Reads;
dr->cur_BytesRead -= dr->prev_BytesRead;
dr->prev_BytesRead += dr->cur_BytesRead;
dr->avg_BytesRead += dr->cur_BytesRead;
dr->cur_Writes -= dr->prev_Writes ;
dr->prev_Writes += dr->cur_Writes ;
dr->avg_Writes += dr->cur_Writes ;
dr->cur_BytesWritten -= dr->prev_BytesWritten ;
dr->prev_BytesWritten += dr->cur_BytesWritten ;
dr->avg_BytesWritten += dr->cur_BytesWritten ;
dr->cur_LatentReadTime -= dr->prev_LatentReadTime ;
dr->prev_LatentReadTime += dr->cur_LatentReadTime ;
dr->avg_LatentReadTime += dr->cur_LatentReadTime ;
dr->cur_LatentWriteTime -= dr->prev_LatentWriteTime ;
dr->prev_LatentWriteTime += dr->cur_LatentWriteTime ;
dr->avg_LatentWriteTime += dr->cur_LatentWriteTime ;
dr->cur_ReadErrors -= dr->prev_ReadErrors ;
dr->prev_ReadErrors += dr->cur_ReadErrors ;
dr->avg_ReadErrors += dr->cur_ReadErrors ;
dr->cur_WriteErrors -= dr->prev_WriteErrors ;
dr->prev_WriteErrors += dr->cur_WriteErrors ;
dr->avg_WriteErrors += dr->cur_WriteErrors ;
dr->cur_ReadRetries -= dr->prev_ReadRetries ;
dr->prev_ReadRetries += dr->cur_ReadRetries ;
dr->avg_ReadRetries += dr->cur_ReadRetries ;
dr->cur_WriteRetries -= dr->prev_WriteRetries ;
dr->prev_WriteRetries += dr->cur_WriteRetries;
dr->avg_WriteRetries += dr->cur_WriteRetries;
dr->cur_TotalReadTime -= dr->prev_TotalReadTime ;
dr->prev_TotalReadTime += dr->cur_TotalReadTime ;
dr->avg_TotalReadTime += dr->cur_TotalReadTime ;
dr->cur_TotalWriteTime -= dr->prev_TotalWriteTime ;
dr->prev_TotalWriteTime += dr->cur_TotalWriteTime ;
dr->avg_TotalWriteTime += dr->cur_TotalWriteTime ;
interval_bytes = dr->cur_BytesRead + dr->cur_BytesWritten;
interval_transfers = dr->cur_Reads + dr->cur_Writes;
interval_time = dr->cur_LatentReadTime + dr->cur_LatentWriteTime;
interval_blocks = interval_bytes / dr->blocksize;
blocks_per_second = interval_blocks / avg_interval;
transfers_per_second = interval_transfers / avg_interval;
mb_per_second = (interval_bytes / avg_interval) / (1024 *1024);
kb_per_transfer = (interval_transfers > 0) ?
((long double)interval_bytes / interval_transfers)
/ 1024 : 0;
ms_per_transaction = (interval_transfers > 0) ?
((long double)interval_time / interval_transfers)
/ 1000 : 0;
fprintf(stdout, "%s %-10s", timebufptr, dr->name);
fprintf(stdout, "%4.0Lf ", transfers_per_second);
fprintf(stdout, "%4.0Lf\n", blocks_per_second);
}
}
static void
exit_average()
{
int i;
if (avg_counter <= 0 )
exit(0);
if (oflag)
{
if (ofd)
close (ofd);
ofd = 0;
}
if (uflag)
{
if(flag_count > 1)
print_column_heading(SAR_CPU, 0, 0);
fprintf(stdout, "Average: %5d ",
(int)avg_cpuload.cpu_ticks[CPU_STATE_USER]
/ (avg_counter ? avg_counter : 1));
fprintf(stdout, "%4d ",
(int)avg_cpuload.cpu_ticks[CPU_STATE_NICE]
/ (avg_counter ? avg_counter : 1));
fprintf(stdout, "%4d ",
(int)avg_cpuload.cpu_ticks[CPU_STATE_SYSTEM]
/ (avg_counter ? avg_counter : 1));
fprintf(stdout, "%4d \n",
(int)avg_cpuload.cpu_ticks[CPU_STATE_IDLE]
/ (avg_counter ? avg_counter : 1));
fflush(stdout);
}
if (gflag)
{
if (flag_count > 1)
print_column_heading(SAR_VMSTAT, 0, 0);
fprintf(stdout, "Average: %8.1f\n",
(float)((avg_vmstat.pageouts / (avg_counter ? avg_counter : 1)) / avg_interval));
fflush(stdout);
}
if (pflag)
{
if (flag_count > 1)
print_column_heading(SAR_VMSTAT, 0, 1);
fprintf(stdout, "Average: %8.1f %8.1f %8.1f\n",
(float)(((float)avg_vmstat.pageins / (avg_counter ? avg_counter : 1)) / avg_interval),
(float)(((float)avg_vmstat.cow_faults / (avg_counter ? avg_counter : 1)) / avg_interval),
(float)(((float)avg_vmstat.faults / (avg_counter ? avg_counter : 1)) / avg_interval));
fflush(stdout);
}
if (dflag)
{
struct drivestats_report *dr;
long double transfers_per_second;
long double kb_per_transfer, mb_per_second;
u_int64_t total_bytes, total_transfers, total_blocks;
u_int64_t total_time;
long double blocks_per_second, ms_per_transaction;
int msdig;
if (flag_count > 1)
print_column_heading(SAR_DRIVESTATS, 0, 0);
for (dr=dr_head; dr; dr=(struct drivestats_report *)dr->next)
{
if (!dr->present)
continue;
fprintf(stdout, " %s %s\n",
dp_table[dr->drivepath_id].BSDName, dp_table[dr->drivepath_id].ioreg_path);
total_bytes = dr->avg_BytesRead + dr->avg_BytesWritten;
total_transfers = dr->avg_Reads + dr->avg_Writes;
total_time = dr->avg_LatentReadTime + dr->avg_LatentWriteTime;
total_blocks = total_bytes / dr->blocksize;
blocks_per_second = total_blocks / avg_interval;
transfers_per_second = total_transfers / avg_interval;
mb_per_second = (total_bytes / avg_interval) / (1024 *1024);
kb_per_transfer = (total_transfers > 0) ?
((long double)total_bytes / total_transfers)
/ 1024 : 0;
ms_per_transaction = (total_transfers > 0) ?
((long double)total_time / total_transfers)
/ 1000 : 0;
msdig = (ms_per_transaction < 100.0) ? 1 : 0;
fprintf(stdout, "Average: %-10s %4.0Lf %4.0Lf\n",
dr->name,
(transfers_per_second / dr->avg_count),
(blocks_per_second / dr->avg_count));
fflush(stdout);
}
}
if (nflag)
{
int avg_count;
if (network_mode & NET_DEV_MODE)
{
if (flag_count > 1)
print_column_heading(SAR_NETSTATS, 0, NET_DEV_MODE);
for (i = 0; i < nr_count; i++)
{
if (!nr_table[i].valid)
continue;
if(nr_table[i].avg_count == 0)
avg_count = 1;
else
avg_count = nr_table[i].avg_count;
fprintf(stdout, "Average: %-8.8s", nr_table[i].tname_unit);
fprintf (stdout, "%8llu ",
((nr_table[i].avg_ipackets / avg_count) / avg_interval));
fprintf (stdout, "%10llu ",
((nr_table[i].avg_ibytes / avg_count) / avg_interval));
fprintf (stdout, "%8llu ",
((nr_table[i].avg_opackets / avg_count) / avg_interval));
fprintf (stdout, "%10llu\n",
((nr_table[i].avg_obytes / avg_count) / avg_interval));
fflush(stdout);
}
}
if (network_mode & NET_EDEV_MODE)
{
if(flag_count > 1)
print_column_heading(SAR_NETSTATS, 0, NET_EDEV_MODE);
for (i = 0; i < nr_count; i++)
{
if (!nr_table[i].valid)
continue;
if(nr_table[i].avg_count == 0)
avg_count = 1;
else
avg_count = nr_table[i].avg_count;
fprintf(stdout, "Average: %-8.8s ", nr_table[i].tname_unit);
fprintf (stdout, "%7llu ",
((nr_table[i].avg_ierrors / avg_count) / avg_interval));
fprintf (stdout, "%7llu ",
((nr_table[i].avg_oerrors / avg_count) / avg_interval));
fprintf (stdout, "%5llu ",
((nr_table[i].avg_collisions / avg_count) / avg_interval));
fprintf (stdout, " %5llu\n",
((nr_table[i].avg_drops / avg_count) / avg_interval));
fflush(stdout);
}
}
}
exit(0);
}
static int
get_drivepath_sample(flag, hdr)
int flag;
struct record_hdr *hdr;
{
size_t datasize;
struct drivepath dp;
struct drivestats_report *dr;
int i, n;
datasize = hdr->rec_count * hdr->rec_size;
if (datasize != sizeof(struct drivepath))
{
skip_data(datasize);
return(0);
}
read_record_data ((char *)&dp, (int)sizeof(struct drivepath), TRUE );
if (dp.state == DPSTATE_NEW)
{
if (dp_table == NULL)
{
if (dp.drivepath_id != 0)
return(-1);
dp_table = (struct drivepath *)malloc(sizeof(struct drivepath));
if (dp_table == NULL)
return(-2);
dp_count = 1;
}
if (dflag)
fprintf(stdout, "New Disk: [%s] %s\n", dp.BSDName, dp.ioreg_path);
for (i = 0; i< dp_count; i++)
{
if (dp_table[i].state == DPSTATE_UNINITIALIZED)
{
if (dp.drivepath_id != i)
{
return (-3);
}
dp_table[i] = dp;
return(1);
}
}
if (dp.drivepath_id != i)
{
return (-4);
}
n = dp_count * 2;
dp_table = (struct drivepath *)realloc(dp_table, n * sizeof(struct drivepath));
bzero(&dp_table[dp_count], dp_count * sizeof(struct drivepath));
dp_table[dp_count] = dp;
dp_count = n;
return(1);
}
else if (dp.state == DPSTATE_CHANGED)
{
if ((dp.drivepath_id < dp_count) && (dp_table[dp.drivepath_id].state != DPSTATE_UNINITIALIZED))
{
if (strcmp(dp_table[dp.drivepath_id].ioreg_path, dp.ioreg_path) != 0)
{
return (-5);
}
else
{
if (dflag)
{
fprintf(stdout, "Change: [%s] %s\n", dp.BSDName,
dp_table[dp.drivepath_id].ioreg_path);
}
strcpy(dp_table[dp.drivepath_id].BSDName, dp.BSDName);
for(dr = dr_head; dr; dr=(struct drivestats_report *)dr->next)
{
if (dr->drivepath_id == dp.drivepath_id)
strcpy(dr->name, dp.BSDName);
}
return(1);
}
}
else
return(-6);
}
return(-7);
}
static void
set_cur_netstats(struct netstats_report *nr, struct netstats *ns)
{
nr->cur_ipackets = ns->net_ipackets;
nr->cur_ibytes = ns->net_ibytes;
nr->cur_opackets = ns->net_opackets;
nr->cur_obytes = ns->net_obytes;
nr->cur_ierrors = ns->net_ierrors;
nr->cur_oerrors = ns->net_oerrors;
nr->cur_collisions = ns->net_collisions;
nr->cur_drops = ns->net_drops;
nr->cur_imcasts = ns->net_imcasts;
nr->cur_omcasts = ns->net_omcasts;
}
static void
init_prev_netstats(struct netstats_report *nr)
{
nr->avg_count = 0;
nr->valid = 1;
nr->present = 1;
nr->prev_ipackets = nr->cur_ipackets;
nr->avg_ipackets = 0;
nr->prev_ibytes = nr->cur_ibytes;
nr->avg_ibytes = 0;
nr->prev_opackets = nr->cur_opackets;
nr->avg_opackets = 0;
nr->prev_obytes = nr->cur_obytes;
nr->avg_obytes = 0;
nr->prev_ierrors = nr->cur_ierrors;
nr->avg_ierrors = 0;
nr->prev_oerrors = nr->cur_oerrors ;
nr->avg_oerrors = 0;
nr->prev_collisions = nr->cur_collisions ;
nr->avg_collisions = 0;
nr->prev_drops = nr->cur_drops ;
nr->avg_drops = 0;
nr->prev_imcasts = nr->cur_imcasts;
nr->avg_imcasts = 0;
nr->prev_omcasts = nr->cur_omcasts;
nr->avg_omcasts = 0;
}
static int
get_netstats_sample(flag, hdr)
int flag;
struct record_hdr *hdr;
{
struct netstats *databuf = NULL;
size_t datasize;
int datacount;
int i, j;
datasize = hdr->rec_count * hdr->rec_size;
datacount = hdr->rec_count;
if (hdr->rec_size != sizeof(struct netstats))
{
skip_data(datasize);
return(0);
}
if((netstat_readbuf == NULL) || (netstat_readbuf_size < datasize))
{
if (netstat_readbuf)
free (netstat_readbuf);
if ((netstat_readbuf = (struct netstats *)malloc(datasize)) == NULL)
{
fprintf(stderr, "sar: malloc failed\n");
exit (EXIT_FAILURE);
}
netstat_readbuf_size = datasize;
}
bzero(netstat_readbuf, netstat_readbuf_size);
databuf = netstat_readbuf;
read_record_data ((char *)databuf, datasize, TRUE );
if (nr_table == NULL)
{
nr_table = (struct netstats_report *)malloc(datacount * sizeof(struct netstats_report));
nr_count = datacount;
bzero(nr_table, (datacount * sizeof(struct netstats_report)));
for (i = 0; i < datacount; i++)
{
if (!(network_mode & NET_PPP_MODE))
{
if (!strncmp(databuf[i].tname_unit, "ppp", 3))
continue;
}
strncpy(nr_table[i].tname_unit, databuf[i].tname_unit, MAX_TNAME_UNIT_SIZE);
nr_table[i].tname_unit[MAX_TNAME_UNIT_SIZE] = '\0';
set_cur_netstats(&nr_table[i], &databuf[i]);
init_prev_netstats(&nr_table[i]);
}
return(1);
}
for (i = 0; i < nr_count; i++)
{
nr_table[i].present = 0;
}
for (i=0; i<datacount; i++)
{
int found;
char *name;
int nr_index;
int n;
name = databuf[i].tname_unit;
found = 0;
if (!(network_mode & NET_PPP_MODE))
{
if (!strncmp(name, "ppp", 3))
continue;
}
for (j=0; j < nr_count && !found; j++)
{
if (nr_table[j].valid)
{
if(!strcmp(nr_table[j].tname_unit, name))
{
found = 1;
nr_table[j].present = 1;
set_cur_netstats(&nr_table[j], &databuf[i]);
}
}
}
if (!found)
{
for (j=0; j < nr_count; j++)
{
if (!nr_table[j].valid)
{
nr_index = j;
goto NEW_ENTRY;
}
}
n = nr_count * 2;
nr_table = (struct netstats_report *)realloc(nr_table, n * sizeof(struct netstats_report));
bzero(&nr_table[nr_count], nr_count * sizeof (struct netstats_report));
nr_index = nr_count;
nr_count = n;
NEW_ENTRY:
strncpy(nr_table[nr_index].tname_unit, databuf[i].tname_unit, MAX_TNAME_UNIT_SIZE);
nr_table[nr_index].tname_unit[MAX_TNAME_UNIT_SIZE] = '\0';
set_cur_netstats(&nr_table[nr_index], &databuf[i]);
init_prev_netstats(&nr_table[nr_index]);
}
}
for (i = 0; i < nr_count; i++)
{
if (nr_table[i].valid)
{
if (nr_table[i].present == 0)
bzero(&nr_table[i], sizeof(struct netstats_report));
}
}
return (1);
}
static void
print_netstats_sample(char *timebufptr)
{
int i;
for (i=0; i < nr_count; i++)
{
if (!nr_table[i].valid)
continue;
if (network_mode & NET_PPP_MODE)
{
if (!strncmp(nr_table[i].tname_unit, "ppp", 3))
{
if ((nr_table[i].cur_ipackets < nr_table[i].prev_ipackets)
&& (nr_table[i].cur_opackets < nr_table[i].prev_opackets))
{
init_prev_netstats(&nr_table[i]);
continue;
}
}
}
nr_table[i].avg_count ++;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_ipackets < nr_table[i].prev_ipackets)
nr_table[i].cur_ipackets += 0x100000000LL;
#endif
nr_table[i].cur_ipackets -= nr_table[i].prev_ipackets;
nr_table[i].prev_ipackets += nr_table[i].cur_ipackets;
nr_table[i].avg_ipackets += nr_table[i].cur_ipackets;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_ibytes < nr_table[i].prev_ibytes)
nr_table[i].cur_ibytes += 0x100000000LL;
#endif
nr_table[i].cur_ibytes -= nr_table[i].prev_ibytes;
nr_table[i].prev_ibytes += nr_table[i].cur_ibytes;
nr_table[i].avg_ibytes += nr_table[i].cur_ibytes;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_opackets < nr_table[i].prev_opackets)
nr_table[i].cur_opackets += 0x100000000LL;
#endif
nr_table[i].cur_opackets -= nr_table[i].prev_opackets;
nr_table[i].prev_opackets += nr_table[i].cur_opackets;
nr_table[i].avg_opackets += nr_table[i].cur_opackets;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_obytes < nr_table[i].prev_obytes)
nr_table[i].cur_obytes += 0x100000000LL;
#endif
nr_table[i].cur_obytes -= nr_table[i].prev_obytes;
nr_table[i].prev_obytes += nr_table[i].cur_obytes;
nr_table[i].avg_obytes += nr_table[i].cur_obytes;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_ierrors < nr_table[i].prev_ierrors)
nr_table[i].cur_ierrors += 0x100000000LL;
#endif
nr_table[i].cur_ierrors -= nr_table[i].prev_ierrors;
nr_table[i].prev_ierrors += nr_table[i].cur_ierrors;
nr_table[i].avg_ierrors += nr_table[i].cur_ierrors;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_oerrors < nr_table[i].prev_oerrors)
nr_table[i].cur_oerrors += 0x100000000LL;
#endif
nr_table[i].cur_oerrors -= nr_table[i].prev_oerrors;
nr_table[i].prev_oerrors += nr_table[i].cur_oerrors;
nr_table[i].avg_oerrors += nr_table[i].cur_oerrors;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_collisions < nr_table[i].prev_collisions)
nr_table[i].cur_collisions += 0x100000000LL;
#endif
nr_table[i].cur_collisions -= nr_table[i].prev_collisions;
nr_table[i].prev_collisions += nr_table[i].cur_collisions;
nr_table[i].avg_collisions += nr_table[i].cur_collisions;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_drops < nr_table[i].prev_drops)
nr_table[i].cur_drops += 0x100000000LL;
#endif
nr_table[i].cur_drops -= nr_table[i].prev_drops;
nr_table[i].prev_drops += nr_table[i].cur_drops;
nr_table[i].avg_drops += nr_table[i].cur_drops;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_imcasts < nr_table[i].prev_imcasts)
nr_table[i].cur_imcasts += 0x100000000LL;
#endif
nr_table[i].cur_imcasts -= nr_table[i].prev_imcasts;
nr_table[i].prev_imcasts += nr_table[i].cur_imcasts;
nr_table[i].avg_imcasts += nr_table[i].cur_imcasts;
#ifdef IFNET_32_BIT_COUNTERS
while (nr_table[i].cur_omcasts < nr_table[i].prev_omcasts)
nr_table[i].cur_omcasts += 0x100000000LL;
#endif
nr_table[i].cur_omcasts -= nr_table[i].prev_omcasts;
nr_table[i].prev_omcasts += nr_table[i].cur_omcasts;
nr_table[i].avg_omcasts += nr_table[i].cur_omcasts;
}
if (!(flag_count > 1))
fprintf(stdout, "\n");
if (network_mode & NET_DEV_MODE)
{
if (flag_count > 1)
print_column_heading(SAR_NETSTATS, timebufptr, NET_DEV_MODE);
for (i=0; i < nr_count; i++)
{
if (!nr_table[i].valid)
continue;
if (!(network_mode & NET_PPP_MODE))
{
if (!strncmp(nr_table[i].tname_unit, "ppp", 3))
{
continue;
}
}
fprintf(stdout, "%s %-8.8s", timebufptr, nr_table[i].tname_unit);
fprintf (stdout, "%8llu ",
(nr_table[i].cur_ipackets / avg_interval));
fprintf (stdout, "%10llu ",
(nr_table[i].cur_ibytes / avg_interval));
fprintf (stdout, "%8llu ",
(nr_table[i].cur_opackets / avg_interval));
fprintf (stdout, "%10llu\n",
(nr_table[i].cur_obytes / avg_interval));
}
}
if (network_mode & NET_EDEV_MODE)
{
if(flag_count > 1)
{
print_column_heading(SAR_NETSTATS, timebufptr, NET_EDEV_MODE);
}
for (i=0; i < nr_count; i++)
{
if (!nr_table[i].valid)
continue;
if (!(network_mode & NET_PPP_MODE))
{
if (!strncmp(nr_table[i].tname_unit, "ppp", 3))
{
continue;
}
}
fprintf(stdout, "%s %-8.8s ", timebufptr, nr_table[i].tname_unit);
fprintf (stdout, "%7llu ",
(nr_table[i].cur_ierrors / avg_interval));
fprintf (stdout, "%7llu ",
(nr_table[i].cur_oerrors / avg_interval));
fprintf (stdout, "%5llu ",
(nr_table[i].cur_collisions / avg_interval));
fprintf (stdout, " %5llu\n",
(nr_table[i].cur_drops / avg_interval));
}
fflush(stdout);
}
}
static void
print_column_heading(int type, char *timebufptr, int mode)
{
char *p;
p = timebufptr;
if (p == NULL)
p = "Average:";
if (!(flag_count > 1))
fprintf(stdout, "\n");
switch (type)
{
case SAR_CPU:
fprintf (stdout, "\n%s %%usr %%nice %%sys %%idle\n", p);
break;
case SAR_VMSTAT:
if (mode == 0)
fprintf(stdout, "\n%s pgout/s\n", p);
else if (mode == 1)
fprintf(stdout, "\n%s pgin/s pflt/s vflt/s\n", p);
break;
case SAR_DRIVESTATS:
fprintf(stdout, "\n%s device r+w/s blks/s\n", p);
break;
case SAR_NETSTATS:
if (mode == NET_DEV_MODE)
{
fprintf(stdout, "\n%s %-8.8s %8.8s %10.10s %8.8s %10.10s\n", p,
" IFACE", "Ipkts/s", "Ibytes/s", "Opkts/s", "Obytes/s");
}
else if (mode == NET_EDEV_MODE)
{
fprintf(stdout, "\n%s %-8.8s %7.7s %7.7s %5s %s\n", p,
" IFACE", "Ierrs/s", "Oerrs/s", "Coll/s", "Drop/s");
}
break;
default:
break;
}
}