diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-06 20:34:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-06 20:34:04 +0200 |
commit | 7d9a1d25e53544c922d5e362180b2703a86d32df (patch) | |
tree | cb5c25f5bfaf78508e3079a11bc944569bae7a3f | |
parent | a348b4557d3d0af411135c23448a2c5a7cd82982 (diff) | |
download | busybox-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>
-rw-r--r-- | procps/top.c | 265 |
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 }; | |||
92 | struct globals { | 92 | struct 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 | ||
202 | static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif) | 202 | static 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 | ||
857 | static 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 | ||
884 | int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 999 | int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
885 | int top_main(int argc UNUSED_PARAM, char **argv) | 1000 | int 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 |