aboutsummaryrefslogtreecommitdiff
path: root/procps/top.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-05-06 20:34:04 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-05-06 20:34:04 +0200
commit7d9a1d25e53544c922d5e362180b2703a86d32df (patch)
treecb5c25f5bfaf78508e3079a11bc944569bae7a3f /procps/top.c
parenta348b4557d3d0af411135c23448a2c5a7cd82982 (diff)
downloadbusybox-w32-7d9a1d25e53544c922d5e362180b2703a86d32df.tar.gz
busybox-w32-7d9a1d25e53544c922d5e362180b2703a86d32df.tar.bz2
busybox-w32-7d9a1d25e53544c922d5e362180b2703a86d32df.zip
top: make it possible to feed commands via pipe
function old new delta handle_input - 492 +492 mult_lvl_cmp 38 49 +11 packed_usage 28247 28257 +10 top_main 1345 928 -417 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/1 up/down: 513/-417) Total: 96 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to '')
-rw-r--r--procps/top.c265
1 files changed, 155 insertions, 110 deletions
diff --git a/procps/top.c b/procps/top.c
index ee6555188..ed8b56173 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -92,9 +92,9 @@ enum { SORT_DEPTH = 3 };
92struct globals { 92struct globals {
93 top_status_t *top; 93 top_status_t *top;
94 int ntop; 94 int ntop;
95 smallint inverted;
95#if ENABLE_FEATURE_TOPMEM 96#if ENABLE_FEATURE_TOPMEM
96 smallint sort_field; 97 smallint sort_field;
97 smallint inverted;
98#endif 98#endif
99#if ENABLE_FEATURE_TOP_SMP_CPU 99#if ENABLE_FEATURE_TOP_SMP_CPU
100 smallint smp_cpu_info; /* one/many cpu info lines? */ 100 smallint smp_cpu_info; /* one/many cpu info lines? */
@@ -194,9 +194,9 @@ static int mult_lvl_cmp(void* a, void* b)
194 for (i = 0; i < SORT_DEPTH; i++) { 194 for (i = 0; i < SORT_DEPTH; i++) {
195 cmp_val = (*sort_function[i])(a, b); 195 cmp_val = (*sort_function[i])(a, b);
196 if (cmp_val != 0) 196 if (cmp_val != 0)
197 return cmp_val; 197 break;
198 } 198 }
199 return 0; 199 return inverted ? -cmp_val : cmp_val;
200} 200}
201 201
202static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif) 202static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif)
@@ -850,8 +850,105 @@ enum {
850 | PSSCAN_PID 850 | PSSCAN_PID
851 | PSSCAN_SMAPS 851 | PSSCAN_SMAPS
852 | PSSCAN_COMM, 852 | PSSCAN_COMM,
853 EXIT_MASK = (unsigned)-1,
853}; 854};
854 855
856#if ENABLE_FEATURE_USE_TERMIOS
857static unsigned handle_input(unsigned scan_mask, unsigned interval)
858{
859 unsigned char c, *p, buf[64];
860 int len;
861 struct pollfd pfd[1];
862
863 pfd[0].fd = 0;
864 pfd[0].events = POLLIN;
865 if (safe_poll(pfd, 1, interval * 1000) <= 0)
866 return scan_mask;
867
868 len = safe_read(STDIN_FILENO, &buf, sizeof(buf)-1);
869 if (len <= 0) { /* error/EOF? */
870 option_mask32 |= OPT_EOF;
871 return scan_mask;
872 }
873
874 buf[len] = 0;
875 p = buf;
876 while ((c = *p++) != 0) {
877 if (c == initial_settings.c_cc[VINTR])
878 return EXIT_MASK;
879 if (c == initial_settings.c_cc[VEOF])
880 return EXIT_MASK;
881 c |= 0x20; /* lowercase */
882 if (c == 'q')
883 return EXIT_MASK;
884 if (c == 'n') {
885 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
886 sort_function[0] = pid_sort;
887 }
888 if (c == 'm') {
889 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
890 sort_function[0] = mem_sort;
891# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
892 sort_function[1] = pcpu_sort;
893 sort_function[2] = time_sort;
894# endif
895 }
896# if ENABLE_FEATURE_SHOW_THREADS
897 if (c == 'h'
898 IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK)
899 ) {
900 scan_mask ^= PSSCAN_TASKS;
901 }
902# endif
903# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
904 if (c == 'p') {
905 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
906 sort_function[0] = pcpu_sort;
907 sort_function[1] = mem_sort;
908 sort_function[2] = time_sort;
909 }
910 if (c == 't') {
911 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
912 sort_function[0] = time_sort;
913 sort_function[1] = mem_sort;
914 sort_function[2] = pcpu_sort;
915 }
916# if ENABLE_FEATURE_TOPMEM
917 if (c == 's') {
918 scan_mask = TOPMEM_MASK;
919 free(prev_hist);
920 prev_hist = NULL;
921 prev_hist_count = 0;
922 sort_field = (sort_field + 1) % NUM_SORT_FIELD;
923 }
924# endif
925 if (c == 'r')
926 inverted ^= 1;
927# if ENABLE_FEATURE_TOP_SMP_CPU
928 /* procps-2.0.18 uses 'C', 3.2.7 uses '1' */
929 if (c == 'c' || c == '1') {
930 /* User wants to toggle per cpu <> aggregate */
931 if (smp_cpu_info) {
932 free(cpu_prev_jif);
933 free(cpu_jif);
934 cpu_jif = &cur_jif;
935 cpu_prev_jif = &prev_jif;
936 } else {
937 /* Prepare for xrealloc() */
938 cpu_jif = cpu_prev_jif = NULL;
939 }
940 num_cpus = 0;
941 smp_cpu_info = !smp_cpu_info;
942 get_jiffy_counts();
943 }
944# endif
945# endif
946 }
947
948 return scan_mask;
949}
950#endif
951
855//usage:#if ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_TOP_SMP_CPU 952//usage:#if ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_TOP_SMP_CPU
856//usage:# define IF_SHOW_THREADS_OR_TOP_SMP(...) __VA_ARGS__ 953//usage:# define IF_SHOW_THREADS_OR_TOP_SMP(...) __VA_ARGS__
857//usage:#else 954//usage:#else
@@ -871,8 +968,9 @@ enum {
871//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/cpu") 968//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/cpu")
872//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/time") 969//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/time")
873//usage: IF_FEATURE_TOPMEM( 970//usage: IF_FEATURE_TOPMEM(
874//usage: "\n"" S: show memory, R: reverse memory sort" 971//usage: "\n"" S: show memory"
875//usage: ) 972//usage: )
973//usage: "\n"" R: reverse sort"
876//usage: IF_SHOW_THREADS_OR_TOP_SMP( 974//usage: IF_SHOW_THREADS_OR_TOP_SMP(
877//usage: "\n"" " 975//usage: "\n"" "
878//usage: IF_FEATURE_SHOW_THREADS("H: toggle threads") 976//usage: IF_FEATURE_SHOW_THREADS("H: toggle threads")
@@ -880,23 +978,34 @@ enum {
880//usage: IF_FEATURE_TOP_SMP_CPU("1: toggle SMP") 978//usage: IF_FEATURE_TOP_SMP_CPU("1: toggle SMP")
881//usage: ) 979//usage: )
882//usage: "\n"" Q,^C: exit" 980//usage: "\n"" Q,^C: exit"
981//usage: "\n"
982//usage: "\n""Options:"
983//usage: "\n"" -b Batch mode"
984//usage: "\n"" -n N Exit after N iterations"
985//usage: "\n"" -d N Delay between updates"
986//usage: IF_FEATURE_TOPMEM(
987//usage: "\n"" -m Same as 's' key"
988//usage: )
989
990/* Interactive testing:
991 * echo sss | ./busybox top
992 * - shows memory screen
993 * echo sss | ./busybox top -bn1 >mem
994 * - saves memory screen - the *whole* list, not first NROWS porcesses!
995 *
996 * TODO: -i STRING param as a better alternative?
997 */
883 998
884int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 999int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
885int top_main(int argc UNUSED_PARAM, char **argv) 1000int top_main(int argc UNUSED_PARAM, char **argv)
886{ 1001{
887 int iterations; 1002 int iterations;
888 unsigned lines, col; 1003 unsigned lines, col;
889 int lines_rem;
890 unsigned interval; 1004 unsigned interval;
891 char *str_interval, *str_iterations; 1005 char *str_interval, *str_iterations;
892 unsigned scan_mask = TOP_MASK; 1006 unsigned scan_mask = TOP_MASK;
893#if ENABLE_FEATURE_USE_TERMIOS 1007#if ENABLE_FEATURE_USE_TERMIOS
894 struct termios new_settings; 1008 struct termios new_settings;
895 struct pollfd pfd[1];
896 unsigned char c;
897
898 pfd[0].fd = 0;
899 pfd[0].events = POLLIN;
900#endif 1009#endif
901 1010
902 INIT_G(); 1011 INIT_G();
@@ -933,15 +1042,6 @@ int top_main(int argc UNUSED_PARAM, char **argv)
933 1042
934 /* change to /proc */ 1043 /* change to /proc */
935 xchdir("/proc"); 1044 xchdir("/proc");
936#if ENABLE_FEATURE_USE_TERMIOS
937 tcgetattr(0, (void *) &initial_settings);
938 memcpy(&new_settings, &initial_settings, sizeof(new_settings));
939 /* unbuffered input, turn off echo */
940 new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
941
942 bb_signals(BB_FATAL_SIGS, sig_catcher);
943 tcsetattr_stdin_TCSANOW(&new_settings);
944#endif
945 1045
946#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 1046#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
947 sort_function[0] = pcpu_sort; 1047 sort_function[0] = pcpu_sort;
@@ -951,21 +1051,41 @@ int top_main(int argc UNUSED_PARAM, char **argv)
951 sort_function[0] = mem_sort; 1051 sort_function[0] = mem_sort;
952#endif 1052#endif
953 1053
954 while (1) { 1054#if ENABLE_FEATURE_USE_TERMIOS
1055 tcgetattr(0, (void *) &initial_settings);
1056 memcpy(&new_settings, &initial_settings, sizeof(new_settings));
1057 if (!OPT_BATCH_MODE) {
1058 /* unbuffered input, turn off echo */
1059 new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
1060 tcsetattr_stdin_TCSANOW(&new_settings);
1061 }
1062
1063 bb_signals(BB_FATAL_SIGS, sig_catcher);
1064
1065 /* Eat initial input, if any */
1066 scan_mask = handle_input(scan_mask, 0);
1067#endif
1068
1069 while (scan_mask != EXIT_MASK) {
955 procps_status_t *p = NULL; 1070 procps_status_t *p = NULL;
956 1071
957 lines = 24; /* default */ 1072 if (OPT_BATCH_MODE) {
958 col = 79; 1073 lines = INT_MAX;
1074 col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
1075 } else {
1076 lines = 24; /* default */
1077 col = 79;
959#if ENABLE_FEATURE_USE_TERMIOS 1078#if ENABLE_FEATURE_USE_TERMIOS
960 /* We output to stdout, we need size of stdout (not stdin)! */ 1079 /* We output to stdout, we need size of stdout (not stdin)! */
961 get_terminal_width_height(STDOUT_FILENO, &col, &lines); 1080 get_terminal_width_height(STDOUT_FILENO, &col, &lines);
962 if (lines < 5 || col < 10) { 1081 if (lines < 5 || col < 10) {
963 sleep(interval); 1082 sleep(interval);
964 continue; 1083 continue;
965 } 1084 }
966#endif 1085#endif
967 if (col > LINE_BUF_SIZE-2) /* +2 bytes for '\n', NUL, */ 1086 if (col > LINE_BUF_SIZE - 2)
968 col = LINE_BUF_SIZE-2; 1087 col = LINE_BUF_SIZE - 2;
1088 }
969 1089
970 /* read process IDs & status for all the processes */ 1090 /* read process IDs & status for all the processes */
971 while ((p = procps_scan(p, scan_mask)) != NULL) { 1091 while ((p = procps_scan(p, scan_mask)) != NULL) {
@@ -1033,15 +1153,11 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1033 qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort); 1153 qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort);
1034 } 1154 }
1035#endif 1155#endif
1036 lines_rem = lines;
1037 if (OPT_BATCH_MODE) {
1038 lines_rem = INT_MAX;
1039 }
1040 if (scan_mask != TOPMEM_MASK) 1156 if (scan_mask != TOPMEM_MASK)
1041 display_process_list(lines_rem, col); 1157 display_process_list(lines, col);
1042#if ENABLE_FEATURE_TOPMEM 1158#if ENABLE_FEATURE_TOPMEM
1043 else 1159 else
1044 display_topmem_process_list(lines_rem, col); 1160 display_topmem_process_list(lines, col);
1045#endif 1161#endif
1046 clearmems(); 1162 clearmems();
1047 if (iterations >= 0 && !--iterations) 1163 if (iterations >= 0 && !--iterations)
@@ -1052,81 +1168,10 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1052 if (option_mask32 & (OPT_b|OPT_EOF)) 1168 if (option_mask32 & (OPT_b|OPT_EOF))
1053 /* batch mode, or EOF on stdin ("top </dev/null") */ 1169 /* batch mode, or EOF on stdin ("top </dev/null") */
1054 sleep(interval); 1170 sleep(interval);
1055 else if (safe_poll(pfd, 1, interval * 1000) > 0) { 1171 else
1056 if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */ 1172 scan_mask = handle_input(scan_mask, interval);
1057 option_mask32 |= OPT_EOF;
1058 continue;
1059 }
1060 if (c == initial_settings.c_cc[VINTR])
1061 break;
1062 c |= 0x20; /* lowercase */
1063 if (c == 'q')
1064 break;
1065 if (c == 'n') {
1066 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
1067 sort_function[0] = pid_sort;
1068 }
1069 if (c == 'm') {
1070 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
1071 sort_function[0] = mem_sort;
1072# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
1073 sort_function[1] = pcpu_sort;
1074 sort_function[2] = time_sort;
1075# endif
1076 }
1077# if ENABLE_FEATURE_SHOW_THREADS
1078 if (c == 'h'
1079 IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK)
1080 ) {
1081 scan_mask ^= PSSCAN_TASKS;
1082 }
1083# endif
1084# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
1085 if (c == 'p') {
1086 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
1087 sort_function[0] = pcpu_sort;
1088 sort_function[1] = mem_sort;
1089 sort_function[2] = time_sort;
1090 }
1091 if (c == 't') {
1092 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
1093 sort_function[0] = time_sort;
1094 sort_function[1] = mem_sort;
1095 sort_function[2] = pcpu_sort;
1096 }
1097# if ENABLE_FEATURE_TOPMEM
1098 if (c == 's') {
1099 scan_mask = TOPMEM_MASK;
1100 free(prev_hist);
1101 prev_hist = NULL;
1102 prev_hist_count = 0;
1103 sort_field = (sort_field + 1) % NUM_SORT_FIELD;
1104 }
1105 if (c == 'r')
1106 inverted ^= 1;
1107# endif
1108# if ENABLE_FEATURE_TOP_SMP_CPU
1109 /* procps-2.0.18 uses 'C', 3.2.7 uses '1' */
1110 if (c == 'c' || c == '1') {
1111 /* User wants to toggle per cpu <> aggregate */
1112 if (smp_cpu_info) {
1113 free(cpu_prev_jif);
1114 free(cpu_jif);
1115 cpu_jif = &cur_jif;
1116 cpu_prev_jif = &prev_jif;
1117 } else {
1118 /* Prepare for xrealloc() */
1119 cpu_jif = cpu_prev_jif = NULL;
1120 }
1121 num_cpus = 0;
1122 smp_cpu_info = !smp_cpu_info;
1123 get_jiffy_counts();
1124 }
1125# endif
1126# endif
1127 }
1128#endif /* FEATURE_USE_TERMIOS */ 1173#endif /* FEATURE_USE_TERMIOS */
1129 } /* end of "while (1)" */ 1174 } /* end of "while (not Q)" */
1130 1175
1131 bb_putchar('\n'); 1176 bb_putchar('\n');
1132#if ENABLE_FEATURE_USE_TERMIOS 1177#if ENABLE_FEATURE_USE_TERMIOS