📄 output.c
字号:
{"HP_l", "flags,state,uid,pid,ppid,cpu,intpri,nice,addr,sz,wchan,tty,time,comm"}, /* HP -l */{"JFMT", "user,pid,ppid,pgid,sess,jobc,state,tname,cputime,command"}, /* Digital j and -j */{"L5FMT", "f,state,uid,pid,ppid,c,pri,nice,addr,sz,wchan,tt,time,ucmd"}, /* Digital -l */{"LFMT", "uid,pid,ppid,cp,pri,nice,vsz,rss,wchan,state,tname,cputime,command"}, /* Digital l */{"OL_X", "pid,start_stack,esp,eip,timeout,alarm,stat,tname,bsdtime,args"}, /* Old i386 Linux X */{"OL_j", "ppid,pid,pgid,sid,tname,tpgid,stat,uid,bsdtime,args"}, /* Old Linux j */{"OL_l", "flags,uid,pid,ppid,priority,nice,vsz,rss,wchan,stat,tname,bsdtime,args"}, /* Old Linux l */{"OL_m", "pid,tname,majflt,minflt,m_trs,m_drs,m_size,m_swap,rss,m_share,vm_lib,m_dt,args"}, /* Old Linux m */{"OL_s", "uid,pid,pending,sig_block,sig_ignore,caught,stat,tname,bsdtime,args"}, /* Old Linux s */{"OL_u", "user,pid,pcpu,pmem,vsz,rss,tname,stat,start_time,bsdtime,args"}, /* Old Linux u */{"OL_v", "pid,tname,stat,bsdtime,maj_flt,m_trs,m_drs,rss,pmem,args"}, /* Old Linux v */{"RD_", "pid,tname,state,bsdtime,comm"}, /* Real Debian default */{"RD_f", "uid,pid,ppid,start_time,tname,bsdtime,args"}, /* Real Debian -f */{"RD_fj", "uid,pid,ppid,start_time,tname,bsdtime,pgid,sid,args"}, /* Real Debian -jf */{"RD_j", "pid,tname,state,bsdtime,pgid,sid,comm"}, /* Real Debian -j */{"RD_l", "flags,state,uid,pid,ppid,priority,nice,wchan,tname,bsdtime,comm"}, /* Real Debian -l */{"RD_lj", "flags,state,uid,pid,ppid,priority,nice,wchan,tname,bsdtime,pgid,sid,comm"}, /* Real Debian -jl */{"RUSAGE", "minflt,majflt,nswap,inblock,oublock,msgsnd,msgrcv,nsigs,nvcsw,nivcsw"}, /* Digital -o "RUSAGE" */{"SCHED", "user,pcpu,pri,usrpri,nice,psxpri,psr,policy,pset"}, /* Digital -o "SCHED" */{"SFMT", "uid,pid,cursig,sig,sigmask,sigignore,sigcatch,stat,tname,command"}, /* Digital s */{"Std_f", "uid_hack,pid,ppid,c,stime,tname,time,cmd"}, /* new -f */{"Std_fl", "f,s,uid_hack,pid,ppid,c,opri,ni,addr,sz,wchan,stime,tname,time,cmd"}, /* -fl */{"Std_l", "f,s,uid,pid,ppid,c,opri,ni,addr,sz,wchan,tname,time,ucmd"}, /* new -l */{"THREAD", "user,pcpu,pri,scnt,wchan,usertime,systime"}, /* Digital -o "THREAD" */{"UFMT", "uname,pid,pcpu,pmem,vsz,rss,tt,state,start,time,command"}, /* Digital u */{"VFMT", "pid,tt,state,time,sl,pagein,vsz,rss,pcpu,pmem,command"}, /* Digital v */{"~", "~"} /* NULL would ruin alphabetical order */};const int macro_array_count = sizeof(macro_array)/sizeof(macro_struct);/*************************** AIX formats ********************//* Convert AIX format codes to normal format specifiers. */const aix_struct aix_array[] = {{'C', "pcpu", "%CPU"},{'G', "group", "GROUP"},{'P', "ppid", "PPID"},{'U', "user", "USER"},{'a', "args", "COMMAND"},{'c', "comm", "COMMAND"},{'g', "rgroup", "RGROUP"},{'n', "nice", "NI"},{'p', "pid", "PID"},{'r', "pgid", "PGID"},{'t', "etime", "ELAPSED"},{'u', "ruser", "RUSER"},{'x', "time", "TIME"},{'y', "tty", "TTY"},{'z', "vsz", "VSZ"},{'~', "~", "~"} /* NULL would ruin alphabetical order */};const int aix_array_count = sizeof(aix_array)/sizeof(aix_struct);/********************* sorting ***************************//* Convert short sorting codes to normal format specifiers. */const shortsort_struct shortsort_array[] = {{'C', "pcpu" },{'G', "tpgid" },{'J', "cstime" },/* {'K', "stime" }, */ /* conflict, system vs. start time */{'M', "maj_flt" },{'N', "cmaj_flt" },{'P', "ppid" },{'R', "resident" },{'S', "share" },{'T', "start_time" },{'U', "uid" }, /* euid */{'c', "cmd" },{'f', "flags" },{'g', "pgrp" },{'j', "cutime" },{'k', "utime" },{'m', "min_flt" },{'n', "cmin_flt" },{'o', "session" },{'p', "pid" },{'r', "rss" },{'s', "size" },{'t', "tty" },{'u', "user" },{'v', "vsize" },{'y', "priority" }, /* nice */{'~', "~" } /* NULL would ruin alphabetical order */};const int shortsort_array_count = sizeof(shortsort_array)/sizeof(shortsort_struct);/*********** print format_array **********//* called by the parser in another file */void print_format_specifiers(void){ const format_struct *walk = format_array; while(*(walk->spec) != '~'){ if(walk->pr != pr_nop) printf("%-12.12s %-8.8s\n", walk->spec, walk->head); walk++; }}/************ comparison functions for bsearch *************/static int compare_format_structs(const void *a, const void *b){ return strcmp(((format_struct*)a)->spec,((format_struct*)b)->spec);}static int compare_macro_structs(const void *a, const void *b){ return strcmp(((macro_struct*)a)->spec,((macro_struct*)b)->spec);}/******** look up structs as needed by the sort & format parsers ******/const shortsort_struct *search_shortsort_array(const int findme){ const shortsort_struct *walk = shortsort_array; while(walk->desc != '~'){ if(walk->desc == findme) return walk; walk++; } return NULL;}const aix_struct *search_aix_array(const int findme){ const aix_struct *walk = aix_array; while(walk->desc != '~'){ if(walk->desc == findme) return walk; walk++; } return NULL;}const format_struct *search_format_array(const char *findme){ format_struct key; key.spec = findme; return bsearch(&key, format_array, format_array_count, sizeof(format_struct), compare_format_structs );}const macro_struct *search_macro_array(const char *findme){ macro_struct key; key.spec = findme; return bsearch(&key, macro_array, macro_array_count, sizeof(macro_struct), compare_macro_structs );}static unsigned int active_cols; /* some multiple of screen_cols *//***** Last chance, avoid needless trunctuation. */static void check_header_width(void){ format_node *walk = format_list; unsigned int total = 0; int was_normal = 0; unsigned int i = 0; unsigned int sigs = 0; while(walk){ switch((walk->flags) & JUST_MASK){ default: total += walk->width; total += was_normal; was_normal = 1; break; case SIGNAL: sigs++; total += walk->width; total += was_normal; was_normal = 1; break; case UNLIMITED: /* could chop this a bit */ if(walk->next) total += walk->width; else total += 3; /* not strlen(walk->name) */ total += was_normal; was_normal = 1; break; case 0: /* AIX */ total += walk->width; was_normal = 0; break; } walk = walk->next; } for(;;){ i++; active_cols = screen_cols * i; if(active_cols>=total) break; if(screen_cols*i >= OUTBUF_SIZE/2) break; /* can't go over */ } wide_signals = (total+sigs*7 <= active_cols); #if 0 printf("123456789-123456789-123456789-123456789-" "123456789-123456789-123456789-123456789\n"); printf("need %d, using %d\n", total, active_cols);#endif}/********** show one process (NULL proc prints header) **********/void show_one_proc(proc_t* p){ /* unknown: maybe set correct & actual to 1, remove +/- 1 below */ int correct = 0; /* screen position we should be at */ int actual = 0; /* screen position we are at */ int camax = 0; /* MAX(correct,actual) */ int amount = 0; /* amount of text that this data is */ int leftpad = 0; /* amount of space this column _could_ need */ int space = 0; /* amount of space we actually need to print */ int dospace = 0; /* previous column determined that we need a space */ int legit = 0; /* legitimately stolen extra space */ format_node *fmt = format_list; static int did_stuff = 0; /* have we ever printed anything? */ if(-1==(long)p){ /* true only once, at the end */ check_header_width(); /* temporary test code */ if(did_stuff) return; /* have _never_ printed anything, but might need a header */ if(!--lines_to_next_header){ lines_to_next_header = header_gap; show_one_proc(NULL); } /* fprintf(stderr, "No processes available.\n"); */ /* legal? */ exit(1); } if(p){ /* not header, maybe we should call ourselves for it */ if(!--lines_to_next_header){ lines_to_next_header = header_gap; show_one_proc(NULL); } } did_stuff = 1; pp = p; /* global, the proc_t struct */ if(active_cols>(int)OUTBUF_SIZE) fprintf(stderr,"Fix bigness error.\n"); /* print row start sequence */ do{ legit = 0; camax = (correct>actual) ? correct : actual; /* set width suggestion which might be ignored */ if(fmt->next) max_rightward = fmt->width; else max_rightward = active_cols-camax; max_leftward = fmt->width + actual - correct; /* TODO check this */ /* prepare data and calculate leftpad */ if(p && fmt->pr) amount = (*fmt->pr)(); else amount = strlen(strcpy(outbuf, fmt->name)); /* AIX or headers */ switch((fmt->flags) & JUST_MASK){ case 0: /* for AIX, assigned outside this file */ leftpad = 0; break; case LEFT: /* bad */ leftpad = 0; break; case RIGHT: /* OK */ leftpad = fmt->width - amount; if(leftpad < 0) leftpad = 0; break; case SIGNAL: /* if the screen is wide enough, use full 16-character output */ if(wide_signals){ leftpad = 16 - amount; legit = 7; }else{ leftpad = 9 - amount; } if(leftpad < 0) leftpad = 0; break; case USER: /* bad */ leftpad = fmt->width - amount; if(leftpad < 0) leftpad = 0; if(!user_is_number) leftpad = 0; break; case WCHAN: /* bad */ if(wchan_is_number){ leftpad = fmt->width - amount; if(leftpad < 0) leftpad = 0; break; }else{ if(fmt->next){ outbuf[fmt->width] = '\0'; /* Must chop, more columns! */ }else{ int chopspot; /* place to chop */ int tmpspace; /* need "space" before it is calculated below */ tmpspace = correct - actual; if(tmpspace<1) tmpspace = dospace; chopspot = active_cols-actual-tmpspace; if(chopspot<1) chopspot=1; /* oops, we (mostly) lose this column... */ outbuf[chopspot] = '\0'; /* chop at screen/buffer limit */ } leftpad = 0; break; } case UNLIMITED: if(fmt->next){ outbuf[fmt->width] = '\0'; /* Must chop, more columns! */ }else{ int chopspot; /* place to chop */ int tmpspace; /* need "space" before it is calculated below */ tmpspace = correct - actual; if(tmpspace<1) tmpspace = dospace; chopspot = active_cols-actual-tmpspace; if(chopspot<1) chopspot=1; /* oops, we (mostly) lose this column... */ outbuf[chopspot] = '\0'; /* chop at screen/buffer limit */ } leftpad = 0; break; default: fputs("bad alignment code\n", stderr); break; } /* At this point: * * amount garbage * actual from previous column * correct from previous column * space gets toasted by the next line of code */ space = correct - actual + leftpad; if(space<1) space=dospace; if(space>SPACE_AMOUNT) space=SPACE_AMOUNT;/* printf("[%d %d %d %d %d %d]", correct,actual,amount,leftpad,space,dospace); */ /* print data, set x position stuff */ actual += fprintf(stdout, "%s", outbuf-space); correct += fmt->width; correct += legit; /* adjust for SIGNAL expansion */ if(fmt->pr && fmt->next && fmt->next->pr){ /* neither is AIX filler */ correct++; dospace=1; } else dospace = 0; /* TODO need this? */ } while(( fmt = fmt->next )); fputs("\n", stdout); /* print row end sequence */}#ifdef TESTINGstatic void sanity_check(void){ format_struct *fs = format_array; while((fs->spec)[0] != '~'){ if(strlen(fs->head) > fs->width) printf("%d %s\n",strlen(fs->head),fs->spec); fs++; }}#endifvoid init_output(void){ memset(whitespace, ' ', PAGE_SIZE);#if 0 mprotect(whitespace, PAGE_SIZE, PROT_READ); /* FIXME may fail if unaligned */ mprotect( (void *)((unsigned long)(whitespace_and_outbuf-PAGE_SIZE) &~ (PAGE_SIZE-1)), PAGE_SIZE, PROT_NONE );#endif seconds_since_boot = uptime(0,0); seconds_since_1970 = time(NULL); time_of_boot = seconds_since_1970 - seconds_since_boot; bytes_main_memory = read_total_main(); switch(getpagesize()){ case 65536: page_shift = 16; break; case 32768: page_shift = 15; break; case 16384: page_shift = 14; break; case 8192: page_shift = 13; break; default: fprintf(stderr, "Unknown page size! (assume 4096)\n"); case 4096: page_shift = 12; break; case 2048: page_shift = 11; break; case 1024: page_shift = 10; break; } check_header_width();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -