#include "top.h"
#include <libutil.h>
static samp_skip_t *samp_skipl;
static samp_print_t *samp_printl;
static samp_print_t *samp_println;
static samp_vprint_t *samp_vprintln;
static samp_vprint_t *samp_veprint;
static const libtop_tsamp_t *samp_tsamp;
extern int disp_bufsize;
extern char *disp_lbuf;
char * pad(char *string, unsigned int width, char just, boolean_t terminate);
static boolean_t
samp_p_eprint(void *a_user_data, const char *a_format, ...);
static int
samp_p_sort(void *a_data, const libtop_psamp_t *a_a, const libtop_psamp_t *a_b);
static int
samp_p_sort_subcomp(top_sort_key_t a_key, const libtop_psamp_t *a_a, const libtop_psamp_t *a_b);
static boolean_t
samp_p_print(void);
boolean_t
samp_p_header_print(void);
static boolean_t
samp_p_legend_print(void);
static boolean_t
samp_p_proc_print(const libtop_psamp_t *a_psamp);
static char *
samp_p_vm_size_delta(unsigned long long a_size, unsigned long long a_prev,
char *a_buf, unsigned a_bufsize);
static char *
samp_p_unsigned_delta(unsigned a_size, unsigned a_prev, char *a_buf,
unsigned a_bufsize);
static char *
samp_p_int_render(int a_int, char *a_buf, unsigned a_bufsize);
static char *
samp_p_unsigned_render(unsigned a_unsigned, char *a_buf, unsigned a_bufsize);
static char *
samp_p_username_render(uid_t a_uid, char *a_buf, unsigned a_bufsize);
static char *
samp_p_vm_size_render(unsigned long long a_size, char *a_buf,
unsigned a_bufsize);
static char *
samp_p_usage_render(const libtop_psamp_t *a_psamp, char *a_buf,
unsigned a_bufsize);
static char *
samp_p_time_render(const libtop_psamp_t *a_psamp, char *a_buf,
unsigned a_bufsize, boolean_t deprecated);
boolean_t
samp_init(samp_skip_t *a_skipl, samp_print_t *a_printl, samp_print_t *a_println,
samp_vprint_t *a_vprintln, samp_vprint_t *a_veprint)
{
samp_skipl = a_skipl;
samp_printl = a_printl;
samp_println = a_println;
samp_vprintln = a_vprintln;
samp_veprint = a_veprint;
if (libtop_init(samp_p_eprint, NULL)) return TRUE;
libtop_set_interval(top_opt_i);
samp_tsamp = libtop_tsamp();
return FALSE;
}
void
samp_fini(void)
{
libtop_fini();
}
boolean_t
samp_run(void)
{
if (top_opt_x && top_opt_c != 'n') {
top_opt_f = FALSE;
top_opt_r = FALSE;
}
if (libtop_sample(top_opt_r, top_opt_f)) return TRUE;
libtop_psort(samp_p_sort, NULL);
return samp_p_print();
}
static boolean_t
samp_p_eprint(void *a_user_data, const char *a_format, ...)
{
boolean_t retval;
va_list ap;
va_start(ap, a_format);
retval = samp_veprint(FALSE, a_format, ap);
va_end(ap);
return retval;
}
static int
samp_p_sort(void *a_data, const libtop_psamp_t *a_a, const libtop_psamp_t *a_b)
{
int retval;
retval = samp_p_sort_subcomp(top_opt_o, a_a, a_b) * (top_opt_o_ascend?1:-1);
if (retval == 0) retval = samp_p_sort_subcomp(top_opt_O, a_a, a_b) * (top_opt_O_ascend?1:-1);
return retval;
}
#define COMP(a,b) (((a)==(b)?0: \
((a)<(b)?-1:1)))
static int
samp_p_sort_subcomp(top_sort_key_t a_key, const libtop_psamp_t *a_a, const libtop_psamp_t *a_b)
{
struct timeval tv_a, tv_b;
const char *user_a, *user_b;
switch (a_key) {
case TOP_SORT_command: return COMP(strcmp(a_a->command, a_b->command),0);
case TOP_SORT_pid: return COMP(a_a->pid, a_b->pid);
case TOP_SORT_prt: return COMP(a_a->prt, a_b->prt);
case TOP_SORT_reg: return COMP(a_a->reg, a_b->reg);
case TOP_SORT_rprvt: return COMP(a_a->rprvt, a_b->rprvt);
case TOP_SORT_rshrd: return COMP(a_a->rshrd, a_b->rshrd);
case TOP_SORT_rsize: return COMP(a_a->rsize, a_b->rsize);
case TOP_SORT_th: return COMP(a_a->th, a_b->th);
case TOP_SORT_vprvt: return COMP(a_a->vprvt, a_b->vprvt);
case TOP_SORT_vsize: return COMP(a_a->vsize, a_b->vsize);
case TOP_SORT_uid: return COMP(a_a->uid, a_b->uid);
case TOP_SORT_cpu:
case TOP_SORT_time:
if(top_opt_c=='a') {
timersub(&a_a->total_time, &a_a->b_total_time, &tv_a);
timersub(&a_b->total_time, &a_b->b_total_time, &tv_b);
} else {
if(a_key==TOP_SORT_cpu) {
timersub(&a_a->total_time, &a_a->p_total_time, &tv_a);
timersub(&a_b->total_time, &a_b->p_total_time, &tv_b);
} else {
tv_a = a_a->total_time;
tv_b = a_b->total_time;
}
}
if(tv_a.tv_sec == tv_b.tv_sec) return COMP(tv_a.tv_usec,tv_b.tv_usec);
else return COMP(tv_a.tv_sec,tv_b.tv_sec);
case TOP_SORT_username:
if (a_a->uid == a_b->uid) return 0;
user_a = libtop_username(a_a->uid);
user_b = libtop_username(a_b->uid);
return COMP(strcmp(user_a, user_b),0);
}
assert(0); }
static boolean_t
samp_p_print(void)
{
const libtop_psamp_t *psamp;
unsigned i;
if (samp_p_header_print()
|| (top_opt_n > 0 && (samp_skipl()
|| samp_p_legend_print()))) return TRUE;
for (i = 1, psamp = libtop_piterate();
psamp != NULL && i <= top_opt_n;
psamp = libtop_piterate()) {
if (top_opt_U == FALSE || psamp->uid == top_opt_U_uid) {
if (samp_p_proc_print(psamp)) return TRUE;
i++;
}
}
return FALSE;
}
boolean_t
samp_p_header_print(void)
{
struct timeval tval;
struct tm tm;
time_t time;
unsigned int i,hour,min,sec;
unsigned long long userticks, systicks, idleticks, totalticks;
float cpu_user, cpu_sys, cpu_idle;
unsigned long long mem_wired, mem_active, mem_inactive, mem_used;
unsigned long long mem_free;
unsigned long long n_ipackets, n_opackets, n_ibytes, n_obytes;
unsigned long long d_rops, d_wops, d_rbytes, d_wbytes;
unsigned long long purgeable_mem;
char time_acc[16],strf_out[30];
char sstr[LIBTOP_NSTATES*(LIBTOP_STATE_MAXLEN + 9)];
char sstr_buf[LIBTOP_STATE_MAXLEN + 9];
char fw_code[6], fw_data[6], fw_linkedit[6];
char vprvt[6], fw_private[6], rshrd[6];
char wired[6], active[6], inactive[6], used[6], free[6];
char vsize[6], fw_vsize[6];
natural_t pageins, pageouts;
char net_ibytes[6], net_obytes[6];
char disk_rbytes[6], disk_wbytes[6];
char xsu_total[6], xsu_used[6], xsu_avail[6];
char purgeable[6];
timersub(&samp_tsamp->time, &samp_tsamp->b_time, &tval);
sec = tval.tv_sec;
min = sec / 60;
hour = min / 60;
snprintf(time_acc, sizeof(time_acc), "%u:%02u:%02u", hour, min % 60, sec % 60);
gettimeofday(&tval, NULL);
time = tval.tv_sec;
localtime_r(&(tval.tv_sec), &tm);
strftime(strf_out,sizeof(strf_out)-1,"%Y/%m/%d %T",&tm);
sstr[0]='\0';
for (i = 0; i < LIBTOP_NSTATES; i++)
if (samp_tsamp->state_breakdown[i] != 0) {
snprintf(sstr_buf, sizeof(sstr_buf),", %d %s",
samp_tsamp->state_breakdown[i], libtop_state_str(i));
strlcat(sstr, sstr_buf, sizeof(sstr));
}
userticks = samp_tsamp->cpu.cpu_ticks[CPU_STATE_USER]
+ samp_tsamp->cpu.cpu_ticks[CPU_STATE_NICE];
systicks = samp_tsamp->cpu.cpu_ticks[CPU_STATE_SYSTEM];
idleticks = samp_tsamp->cpu.cpu_ticks[CPU_STATE_IDLE];
if(top_opt_c=='a') {
userticks -= (samp_tsamp->b_cpu.cpu_ticks[CPU_STATE_USER]
+samp_tsamp->b_cpu.cpu_ticks[CPU_STATE_NICE]);
systicks -= samp_tsamp->b_cpu.cpu_ticks[CPU_STATE_SYSTEM];
idleticks -= samp_tsamp->b_cpu.cpu_ticks[CPU_STATE_IDLE];
}
if(top_opt_c=='d' || top_opt_c=='n') {
userticks -= (samp_tsamp->p_cpu.cpu_ticks[CPU_STATE_USER]
+samp_tsamp->p_cpu.cpu_ticks[CPU_STATE_NICE]);
systicks -= samp_tsamp->p_cpu.cpu_ticks[CPU_STATE_SYSTEM];
idleticks -= samp_tsamp->p_cpu.cpu_ticks[CPU_STATE_IDLE];
}
if(userticks < 0) userticks = 0;
if(systicks < 0) systicks = 0;
if(idleticks < 0) idleticks = 0;
totalticks = userticks + systicks + idleticks;
if (totalticks != 0) {
cpu_user = ((float)(100 * userticks)) / ((float)totalticks);
cpu_sys = ((float)(100 * systicks)) / ((float)totalticks);
cpu_idle = ((float)(100 * idleticks)) / ((float)totalticks);
} else {
cpu_user = 0.0;
cpu_sys = 0.0;
cpu_idle = 0.0;
}
mem_wired = (unsigned long long) samp_tsamp->vm_stat.wire_count * samp_tsamp->pagesize;
mem_active = (unsigned long long) samp_tsamp->vm_stat.active_count * samp_tsamp->pagesize;
mem_inactive = (unsigned long long) samp_tsamp->vm_stat.inactive_count * samp_tsamp->pagesize;
mem_used = (unsigned long long) mem_wired + mem_active + mem_inactive;
mem_free = (unsigned long long) samp_tsamp->vm_stat.free_count * samp_tsamp->pagesize;
pageins = samp_tsamp->vm_stat.pageins;
pageouts = samp_tsamp->vm_stat.pageouts;
if(top_opt_c=='a') {
pageins -= samp_tsamp->b_vm_stat.pageins;
pageouts -= samp_tsamp->b_vm_stat.pageouts;
}
if(top_opt_c=='d') {
pageins -= samp_tsamp->p_vm_stat.pageins;
pageouts -= samp_tsamp->p_vm_stat.pageouts;
}
if(top_opt_x) {
strftime(disp_lbuf, disp_bufsize-1,"%T",&tm);
if(top_opt_c=='a') {
strlcat(disp_lbuf, " ", disp_bufsize);
strlcat(disp_lbuf,time_acc, disp_bufsize);
}
if(disp_bufsize>40) pad(disp_lbuf, disp_bufsize-1, '$', TRUE);
else pad(disp_lbuf, 80, '$', TRUE);
snprintf(disp_lbuf, disp_bufsize, "Processes: %u total%s... %u threads",samp_tsamp->nprocs, sstr,
samp_tsamp->threads);
disp_lbuf[strlen(disp_lbuf)]=' ';
if (samp_println("%s\n", disp_lbuf)
|| samp_println("\
Load Avg: %5.2f, %5.2f, %5.2f CPU usage: %5.2f%% user, %5.2f%% sys, %5.2f%% idle",
samp_tsamp->loadavg[0], samp_tsamp->loadavg[1], samp_tsamp->loadavg[2],
cpu_user, cpu_sys, cpu_idle))
return TRUE;
} else {
if(top_opt_c=='a') {
if (samp_println("\
Time: %s (%s). Threads: %u. Procs: %u%s.", strf_out, time_acc,
samp_tsamp->threads, samp_tsamp->nprocs,sstr)) return TRUE;
} else {
if (samp_println("\
Time: %s. Threads: %u. Procs: %u%s.", strf_out,
samp_tsamp->threads, samp_tsamp->nprocs,sstr)) return TRUE;
}
if(samp_println("\
LoadAvg: %5.2f, %5.2f, %5.2f. CPU: %5.2f%% user, %5.2f%% sys, %5.2f%% idle.",
samp_tsamp->loadavg[0], samp_tsamp->loadavg[1], samp_tsamp->loadavg[2],
cpu_user, cpu_sys, cpu_idle))
return TRUE;
}
if(!top_opt_x || (top_opt_c!='a' && top_opt_c!='d')) {
if (top_opt_f && samp_println("\
SharedLibs: num = %4u, resident = %5s code, %5s data, %5s linkedit.",
samp_tsamp->fw_count,
samp_p_vm_size_render(samp_tsamp->fw_code, fw_code, sizeof(fw_code)),
samp_p_vm_size_render(samp_tsamp->fw_data, fw_data, sizeof(fw_data)),
samp_p_vm_size_render(samp_tsamp->fw_linkedit, fw_linkedit, sizeof(fw_linkedit))))
return TRUE;
if (top_opt_r && samp_println("\
MemRegions: num = %5u, resident = %5s + %5s private, %5s shared.",
samp_tsamp->reg,
samp_p_vm_size_render(samp_tsamp->rprvt, vprvt, sizeof(vprvt)),
samp_p_vm_size_render(samp_tsamp->fw_private, fw_private, sizeof(fw_private)),
samp_p_vm_size_render(samp_tsamp->rshrd, rshrd, sizeof(rshrd))))
return TRUE;
if (samp_println("\
PhysMem: %5s wired, %5s active, %5s inactive, %5s used, %5s free.",
samp_p_vm_size_render(mem_wired, wired, sizeof(wired)),
samp_p_vm_size_render(mem_active, active, sizeof(active)),
samp_p_vm_size_render(mem_inactive, inactive, sizeof(inactive)),
samp_p_vm_size_render(mem_used, used, sizeof(used)),
samp_p_vm_size_render(mem_free, free, sizeof(free))))
return TRUE;
if (top_opt_f) samp_p_vm_size_render(samp_tsamp->fw_vsize, fw_vsize, sizeof(fw_vsize));
else fw_vsize[0]='\0';
purgeable_mem = (samp_tsamp->vm_stat.purgeable_count * samp_tsamp->pagesize);
if(!top_opt_x) {
if (samp_println("\
VirtMem: %5s%s%5s, %10u pagein%s, %10u pageout%s.",
samp_p_vm_size_render(samp_tsamp->vsize, vsize,sizeof(vsize)),
fw_vsize[0]?" + ":"", fw_vsize, pageins, pageins == 1 ? "" : "s",
pageouts, pageouts == 1 ? "" : "s")) return TRUE;
} else {
if (top_opt_c!='d' && samp_println("VM: %s + %s %u(%u) pageins, %u(%u) pageouts",
samp_p_vm_size_render(samp_tsamp->vsize, vsize, sizeof(vsize)),
samp_p_vm_size_render(samp_tsamp->fw_vsize, fw_vsize, sizeof(fw_vsize)),
samp_tsamp->vm_stat.pageins,
samp_tsamp->vm_stat.pageins - samp_tsamp->p_vm_stat.pageins,
samp_tsamp->vm_stat.pageouts,
(samp_tsamp->vm_stat.pageouts
- samp_tsamp->p_vm_stat.pageouts))) return TRUE;
}
purgeable_mem = (samp_tsamp->vm_stat.purgeable_count * samp_tsamp->pagesize);
if(!top_opt_x && top_opt_S && samp_println("Swap: %5s total, %5s used, %5s free. Purgeable: %5s %10u purges",
(samp_tsamp->xsu_is_valid ?
samp_p_vm_size_render(samp_tsamp->xsu.xsu_total, xsu_total,sizeof(xsu_total)) : "n/a"),
(samp_tsamp->xsu_is_valid ?
samp_p_vm_size_render(samp_tsamp->xsu.xsu_used, xsu_used,sizeof (xsu_used)) : "n/a"),
(samp_tsamp->xsu_is_valid ?
samp_p_vm_size_render(samp_tsamp->xsu.xsu_avail, xsu_avail, sizeof (xsu_avail)) : "n/a"),
(samp_tsamp->purgeable_is_valid ?
samp_p_vm_size_render(purgeable_mem,purgeable, sizeof (purgeable)) : "n/a"),
samp_tsamp->vm_stat.purges)) return TRUE;
if (top_opt_x && top_opt_S && samp_println("Swap: %s + %s free Purgeable: %s %u(%u) pages purged",
(samp_tsamp->xsu_is_valid ?
samp_p_vm_size_render(samp_tsamp->xsu.xsu_used, xsu_used, sizeof(xsu_used)) : "n/a"),
(samp_tsamp->xsu_is_valid ?
samp_p_vm_size_render(samp_tsamp->xsu.xsu_avail, xsu_avail, sizeof (xsu_avail)) : "n/a"),
(samp_tsamp->purgeable_is_valid ?
samp_p_vm_size_render(purgeable_mem, purgeable, sizeof (purgeable)) : "n/a"),
samp_tsamp->vm_stat.purges,
(samp_tsamp->vm_stat.purges
- samp_tsamp->p_vm_stat.purges))) return TRUE;
}
if(top_opt_c=='n') return FALSE;
n_ipackets = samp_tsamp->net_ipackets;
n_opackets = samp_tsamp->net_opackets;
n_ibytes = samp_tsamp->net_ibytes;
n_obytes = samp_tsamp->net_obytes;
d_rops = samp_tsamp->disk_rops;
d_wops = samp_tsamp->disk_wops;
d_rbytes = samp_tsamp->disk_rbytes;
d_wbytes = samp_tsamp->disk_wbytes;
if(top_opt_c=='a') {
n_ipackets -= samp_tsamp->b_net_ipackets;
n_opackets -= samp_tsamp->b_net_opackets;
n_ibytes -= samp_tsamp->b_net_ibytes;
n_obytes -= samp_tsamp->b_net_obytes;
d_rops -= samp_tsamp->b_disk_rops;
d_wops -= samp_tsamp->b_disk_wops;
d_rbytes -= samp_tsamp->b_disk_rbytes;
d_wbytes -= samp_tsamp->b_disk_wbytes;
}
if(top_opt_c=='d') {
n_ipackets -= samp_tsamp->p_net_ipackets;
n_opackets -= samp_tsamp->p_net_opackets;
n_ibytes -= samp_tsamp->p_net_ibytes;
n_obytes -= samp_tsamp->p_net_obytes;
d_rops -= samp_tsamp->p_disk_rops;
d_wops -= samp_tsamp->p_disk_wops;
d_rbytes -= samp_tsamp->p_disk_rbytes;
d_wbytes -= samp_tsamp->p_disk_wbytes;
}
if(top_opt_x) {
if (samp_println("Networks: %10llu ipkts/%6lluK %10llu opkts /%lluK",
n_ipackets, n_ibytes/1024, n_opackets, n_obytes/1024)
|| samp_println("Disks: %10llu reads/%6lluK %10llu writes/%lluK",
d_rops, d_rbytes/1024, d_wops, d_wbytes/1024)
|| samp_println("VM: %10u pageins %u pageouts",
pageins, pageouts)) return TRUE;
} else {
if (samp_println("\
Networks: packets = %10llu in, %10llu out, data = %5s in, %5s out.", n_ipackets, n_opackets,
samp_p_vm_size_render(n_ibytes, net_ibytes, sizeof(net_ibytes)),
samp_p_vm_size_render(n_obytes, net_obytes, sizeof(net_obytes)))
|| samp_println("\
Disks: operations = %10llu in, %10llu out, data = %5s in, %5s out.", d_rops, d_wops,
samp_p_vm_size_render(d_rbytes, disk_rbytes, sizeof(disk_rbytes)),
samp_p_vm_size_render(d_wbytes, disk_wbytes, sizeof(disk_wbytes)))
) return TRUE;
}
return FALSE;
}
boolean_t
samp_p_legend_print(void)
{
char *legend;
if(top_opt_P_legend) legend=top_opt_P_legend;
else switch(top_opt_c) {
case 'a': legend=top_opt_x?LEGEND_CA:LEGEND_XCA; break;
case 'e': legend=top_opt_x?LEGEND_CE:LEGEND_XCE; break;
case 'd': legend=top_opt_x?LEGEND_CD:LEGEND_XCD; break;
case 'n':
if(top_opt_w) legend=top_opt_x?LEGEND_CNW:LEGEND_XCNW;
else legend=top_opt_x?LEGEND_CN:LEGEND_XCN;
break;
default: assert(0);
}
return samp_println("%s",legend);
}
size_t str_char_spn(const char *s, char c) {
char search[2]={c,0};
return strspn(s,search);
}
size_t str_char_cspn(const char *s, char c) {
char search[2]={c,0};
return strcspn(s,search);
}
void delete_char(char *s) {
while(s[0]) {
s[0]=s[1];
s++;
}
}
char * pad(char *string, unsigned int width, char just, boolean_t terminate) {
unsigned int len;
len=strlen(string);
assert(len <= width);
switch(just) {
case '^': memset(string+len, ' ', width-len);
break;
case '$':
memmove(string+width-len, string, len);
memset(string, ' ', width-len);
break;
default: assert(0);
}
if(terminate) string[width]='\0';
return string;
}
static unsigned int
parse_field(const char *format)
{
int length;
if(format==NULL || strlen(format)<2) return 0;
if(format[0]!=FORMAT_LEFT && format[0]!=FORMAT_RIGHT) return 0;
if(strchr(VALID_FORMATS,format[1])==NULL) return 0;
length=str_char_spn(format+1,format[1])+1;
if(length<2) return 0;
return length;
}
char *
render_format_string(char *string,const libtop_psamp_t *a_psamp)
{
char *ptr=string,temp_char,just,type;
int length;
task_events_info_data_t events;
if(ptr == NULL || a_psamp==NULL) return NULL;
events=a_psamp->events;
switch(top_opt_c) {
case 'a':
events.faults-=a_psamp->b_events.faults;
events.pageins-=a_psamp->b_events.pageins;
events.cow_faults-=a_psamp->b_events.cow_faults;
events.messages_sent-=a_psamp->b_events.messages_sent;
events.messages_received-=a_psamp->b_events.messages_received;
events.syscalls_mach-=a_psamp->b_events.syscalls_mach;
events.syscalls_unix-=a_psamp->b_events.syscalls_unix;
events.csw-=a_psamp->b_events.csw;
break;
case 'd':
events.faults-=a_psamp->p_events.faults;
events.pageins-=a_psamp->p_events.pageins;
events.cow_faults-=a_psamp->p_events.cow_faults;
events.messages_sent-=a_psamp->p_events.messages_sent;
events.messages_received-=a_psamp->p_events.messages_received;
events.syscalls_mach-=a_psamp->p_events.syscalls_mach;
events.syscalls_unix-=a_psamp->p_events.syscalls_unix;
events.csw-=a_psamp->p_events.csw;
break;
case 'e':
break;
default:
bzero((void *)&events, sizeof(events));
}
while(strlen(ptr)>1) {
length=parse_field(ptr);
if(length==0) {
ptr++;
length=strcspn(ptr,VALID_ESCAPES);
if(length==0 && ptr[0]==0) return string;
ptr+=length;
continue;
} else {
assert(length<=strlen(ptr));
temp_char=ptr[length];
just=ptr[0]; type=ptr[1];
switch(type) {
case FORMAT_PID: samp_p_unsigned_render(a_psamp->pid, ptr, length+1); break;
case FORMAT_THREADS: samp_p_unsigned_render(a_psamp->th, ptr, length+1); break;
case FORMAT_PORTS: samp_p_unsigned_render(a_psamp->prt, ptr, length+1); break;
case FORMAT_REGIONS: samp_p_unsigned_render(a_psamp->reg, ptr, length+1); break;
case FORMAT_UID: samp_p_unsigned_render(a_psamp->uid, ptr, length+1); break;
case FORMAT_COMMAND: strncpy(ptr,a_psamp->command,length); ptr[length]='\0'; break;
case FORMAT_PERCENT_CPU: samp_p_usage_render(a_psamp, ptr, length+1); break;
case FORMAT_TIME: samp_p_time_render(a_psamp, ptr, length+1, FALSE); break;
case FORMAT_RPRVT: samp_p_vm_size_render(a_psamp->rprvt, ptr, length+1); break;
case FORMAT_RSHRD: samp_p_vm_size_render(a_psamp->rshrd, ptr, length+1); break;
case FORMAT_RSIZE: samp_p_vm_size_render(a_psamp->rsize, ptr, length+1); break;
case FORMAT_VPRVT: samp_p_vm_size_render(a_psamp->vprvt, ptr, length+1); break;
case FORMAT_VSIZE: samp_p_vm_size_render(a_psamp->vsize, ptr, length+1); break;
case FORMAT_USERNAME: samp_p_username_render(a_psamp->uid, ptr, length+1); break;
case FORMAT_FAULTS: samp_p_int_render(events.faults, ptr, length+1); break;
case FORMAT_PAGEINS: samp_p_int_render(events.pageins, ptr, length+1); break;
case FORMAT_COW_FAULTS: samp_p_int_render(events.cow_faults, ptr, length+1); break;
case FORMAT_MSGS_SENT: samp_p_int_render(events.messages_sent, ptr, length+1); break;
case FORMAT_MSGS_RECEIVED: samp_p_int_render(events.messages_received, ptr, length+1); break;
case FORMAT_BSYSCALL: samp_p_int_render(events.syscalls_unix, ptr, length+1); break;
case FORMAT_MSYSCALL: samp_p_int_render(events.syscalls_mach, ptr, length+1); break;
case FORMAT_CSWITCH: samp_p_int_render(events.csw, ptr, length+1); break;
case FORMAT_TIME_HHMMSS: samp_p_time_render(a_psamp, ptr, length+1, TRUE); break;
default:
printf("Error, invalid format char %c\n",type);
exit(0);
}
pad(ptr, length, just, FALSE);
ptr[length]=temp_char;
ptr += length;
if(ptr[0] == FORMAT_DELTA) {
length=str_char_spn(ptr, FORMAT_DELTA);
switch(type) {
case FORMAT_PORTS: samp_p_unsigned_delta(a_psamp->prt, a_psamp->p_prt, ptr, length+1); break;
case FORMAT_RPRVT: samp_p_vm_size_delta(a_psamp->rprvt, a_psamp->p_rprvt, ptr, length+1); break;
case FORMAT_RSHRD: samp_p_vm_size_delta(a_psamp->rshrd, a_psamp->p_rshrd, ptr, length+1); break;
case FORMAT_RSIZE: samp_p_vm_size_delta(a_psamp->rsize, a_psamp->p_rsize, ptr, length+1); break;
case FORMAT_VPRVT: samp_p_vm_size_delta(a_psamp->vprvt, a_psamp->p_vprvt, ptr, length+1); break;
case FORMAT_VSIZE: samp_p_vm_size_delta(a_psamp->vsize, a_psamp->p_vsize, ptr, length+1); break;
default:
printf("Error, delta not supported with format char %c\n",type);
exit(0);
}
ptr += length;
}
}
}
return string;
}
static boolean_t
samp_p_proc_print(const libtop_psamp_t *a_psamp)
{
char *format, *render_buf;
if(top_opt_p_format) format=top_opt_p_format;
else switch(top_opt_c) {
case 'a': format=top_opt_x?FORMAT_CA:FORMAT_XCA; break;
case 'e': format=top_opt_x?FORMAT_CE:FORMAT_XCE; break;
case 'd': format=top_opt_x?FORMAT_CD:FORMAT_XCD; break;
case 'n':
if(top_opt_w) format=top_opt_x?FORMAT_CNW:FORMAT_XCNW;
else format=top_opt_x?FORMAT_CN:FORMAT_XCN;
break;
default: assert(0);
}
render_buf=malloc(strlen(format)+1);
if(render_buf==NULL) return TRUE;
strcpy(render_buf,format);
if(samp_println("%s",render_format_string(render_buf,a_psamp))) return TRUE;
free(render_buf);
return FALSE;
}
static char *
samp_p_vm_size_delta(unsigned long long a_size, unsigned long long a_prev,
char *a_buf, unsigned a_bufsize)
{
char *p=a_buf;
assert(a_bufsize > 1);
if(a_bufsize==2) {
if(a_size == a_prev) p[0]=' ';
if(a_size < a_prev) p[0]='-';
if(a_size > a_prev) p[0]='+';
return a_buf;
}
if (a_size == a_prev) {
a_buf[0] = '\0';
pad(a_buf,a_bufsize-1,'^',FALSE);
return a_buf;
}
*p++='(';
if (a_size > a_prev)
samp_p_vm_size_render(a_size - a_prev, p, a_bufsize - 2);
else {
*p='-';
samp_p_vm_size_render(a_prev - a_size, p+1, a_bufsize - 3);
}
pad(p,a_bufsize-3,'$',FALSE);
p[a_bufsize-3]=')';
return a_buf;
}
static char *
samp_p_unsigned_delta(unsigned a_size, unsigned a_prev, char *a_buf,
unsigned a_bufsize)
{
char *p=a_buf;
assert(a_bufsize > 1);
if(a_bufsize==2) {
if(a_size == a_prev) p[0]=' ';
if(a_size < a_prev) p[0]='-';
if(a_size > a_prev) p[0]='+';
return a_buf;
}
if (a_size == a_prev) {
a_buf[0] = '\0';
pad(a_buf,a_bufsize-1,'^', FALSE);
return a_buf;
}
*p++='(';
samp_p_int_render(a_size - a_prev, p, a_bufsize - 2);
pad(p,a_bufsize-3,'$',FALSE);
p[a_bufsize-3]=')';
return a_buf;
}
static char *
samp_p_int_render(int a_int, char *a_buf, unsigned a_bufsize)
{
int len;
assert(a_bufsize >= 2);
len = snprintf(a_buf, a_bufsize, "%d", a_int);
if (len >= a_bufsize) {
memset(a_buf, '>', a_bufsize - 1);
a_buf[a_bufsize - 1] = '\0';
}
return a_buf;
}
static char *
samp_p_unsigned_render(unsigned a_unsigned, char *a_buf, unsigned a_bufsize)
{
int len;
assert(a_bufsize >= 2);
len = snprintf(a_buf, a_bufsize, "%u", a_unsigned);
if (len >= a_bufsize) {
memset(a_buf, '>', a_bufsize - 1);
a_buf[a_bufsize - 1] = '\0';
}
return a_buf;
}
static char *
samp_p_username_render(uid_t a_uid, char *a_buf, unsigned a_bufsize)
{
const char *user;
user = libtop_username(a_uid);
if (user != NULL) strlcpy(a_buf, user, a_bufsize);
else strlcpy(a_buf, "???", a_bufsize);
return a_buf;
}
static char *
samp_p_vm_size_render(unsigned long long a_size, char *a_buf,
unsigned a_bufsize)
{
humanize_number(a_buf, a_bufsize, a_size, "", HN_AUTOSCALE, HN_NOSPACE);
return a_buf;
}
static char *
samp_p_usage_render(const libtop_psamp_t *a_psamp, char *a_buf,
unsigned a_bufsize)
{
struct timeval elapsed_tv, used_tv;
unsigned long long elapsed_us, used_us;
int whole=0, part=0;
if (a_psamp->p_seq == 0) {
strcpy(a_buf," 0.0");
return a_buf;
}
switch (top_opt_c) {
case 'a':
timersub(&samp_tsamp->time, &samp_tsamp->b_time, &elapsed_tv);
timersub(&a_psamp->total_time, &a_psamp->b_total_time, &used_tv);
break;
case 'e': case 'd': case 'n':
timersub(&samp_tsamp->time, &samp_tsamp->p_time, &elapsed_tv);
timersub(&a_psamp->total_time, &a_psamp->p_total_time, &used_tv);
break;
default: assert(0);
}
elapsed_us = (unsigned long long)elapsed_tv.tv_sec * 1000000ULL
+ (unsigned long long)elapsed_tv.tv_usec;
used_us = (unsigned long long)used_tv.tv_sec * 1000000ULL
+ (unsigned long long)used_tv.tv_usec;
whole = (used_us * 100ULL) / elapsed_us;
part = (((used_us * 100ULL) - (whole * elapsed_us)) * 10ULL) / elapsed_us;
snprintf(a_buf, a_bufsize, "%d.%01d", whole, part);
return a_buf;
}
static char *
samp_p_time_render(const libtop_psamp_t *a_psamp, char *a_buf, unsigned a_bufsize, boolean_t deprecated)
{
struct timeval tv;
unsigned usec, sec, min, hour, day;
if(top_opt_c=='a') timersub(&a_psamp->total_time, &a_psamp->b_total_time, &tv);
else tv = a_psamp->total_time;
usec = tv.tv_usec;
sec = tv.tv_sec;
min = sec / 60;
hour = min / 60;
day = hour / 24;
if(deprecated) {
if (min < 100) snprintf(a_buf, a_bufsize, "%u:%02u.%02u", min, sec % 60, usec / 10000);
else if (hour < 100) snprintf(a_buf, a_bufsize, "%u:%02u:%02u", hour, min % 60, sec % 60);
else snprintf(a_buf, a_bufsize, "%u hrs", hour);
} else {
if (sec < 60) snprintf(a_buf, a_bufsize, "%u.%02us", sec, usec / 10000);
else if (min < 60) snprintf(a_buf, a_bufsize, "%um%02us", min, sec - min * 60);
else if (hour < 24) snprintf(a_buf, a_bufsize, "%uh%02um", hour, min - hour * 60);
else if (day < 100) snprintf(a_buf, a_bufsize, "%ud%02uh", day, hour - day * 24);
else snprintf(a_buf, a_bufsize, "%ud", day);
}
return a_buf;
}