├── .gitignore ├── snippets ├── ps-threads.md ├── ps-cpu.md ├── ps-mem.md ├── ps-wchan.md ├── log.md ├── dts-tags.md ├── str.md ├── duplicates.md ├── gdb-print-prepare.md ├── doxygen-bootstrap.md └── load-watch.md ├── stack_trace_check.cpp ├── instrument-tracer.mk ├── gdb-print-demo.c ├── Makefile ├── ctracer-testpp.cpp ├── stack_trace.cpp ├── tracer-hpp-test.cpp ├── ctracer-test.c ├── instrument-tracer.cc ├── README.md ├── tracer.hpp ├── utils.py ├── ctracer.h ├── LICENSE └── lib.sh /.gitignore: -------------------------------------------------------------------------------- 1 | ctracer-test 2 | ctracer-test.ko 3 | ctracer-test.mod 4 | stack_trace_check 5 | -------------------------------------------------------------------------------- /snippets/ps-threads.md: -------------------------------------------------------------------------------- 1 | ps-threads - lists processes with threads 2 | ==== 3 | 4 | 5 | ``` bash 6 | alias ps-threads='ps -ALf' 7 | ``` 8 | -------------------------------------------------------------------------------- /snippets/ps-cpu.md: -------------------------------------------------------------------------------- 1 | ps-cpu - lists most CPU consuming processes 2 | ==== 3 | 4 | 5 | ``` bash 6 | alias ps-cpu='ps -e -o pcpu,pid,comm --sort -%cpu | head -n 10' 7 | ``` 8 | -------------------------------------------------------------------------------- /snippets/ps-mem.md: -------------------------------------------------------------------------------- 1 | ps-mem - lists most memory consuming processes 2 | ==== 3 | 4 | 5 | ``` bash 6 | alias ps-mem='ps -e -o pmem,vsz,rss,pid,comm --sort -%mem | head -n 10' 7 | ``` 8 | -------------------------------------------------------------------------------- /snippets/ps-wchan.md: -------------------------------------------------------------------------------- 1 | ps-wchan - shows what processes are waiting for, used in debugging blocked processes 2 | ==== 3 | 4 | 5 | ``` bash 6 | alias ps-wchan='ps -e -o pid,comm,wchan' 7 | ``` 8 | -------------------------------------------------------------------------------- /stack_trace_check.cpp: -------------------------------------------------------------------------------- 1 | 2 | extern "C" int stack_trace(); 3 | 4 | extern "C" void c_func() 5 | { 6 | stack_trace(); 7 | } 8 | 9 | int main() 10 | { 11 | []() { c_func();}(); 12 | } 13 | -------------------------------------------------------------------------------- /instrument-tracer.mk: -------------------------------------------------------------------------------- 1 | CXXFLAGS+=-rdynamic -finstrument-functions -finstrument-functions-exclude-file-list=/usr/include/,instrument-tracer.cc 2 | instrument-tracer.o: CXXFLAGS+=-std=c++17 3 | LDLIBS+=-ldl 4 | -------------------------------------------------------------------------------- /snippets/log.md: -------------------------------------------------------------------------------- 1 | log - safely prints messages to stderr 2 | ==== 3 | 4 | 5 | ``` bash 6 | log() 7 | { 8 | # Note: echo "$@" > /dev/stderr - resets stderr 9 | ( 1>&2 echo "$@" ) 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /snippets/dts-tags.md: -------------------------------------------------------------------------------- 1 | dts-tags - extacts tags (ctags format) from device tree source files 2 | ==== 3 | 4 | 5 | ``` bash 6 | dts-tags() 7 | { 8 | grep -oH '\w\+:' "$@" | awk -F: '{print $2"\t"$1"\t/"$2":"}' | LC_ALL=C sort 9 | } 10 | ``` 11 | -------------------------------------------------------------------------------- /gdb-print-demo.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | Usage: 4 | 5 | Compile the file with debug info: 6 | make -B CFLAGS=-g gdb-print-demo 7 | 8 | Generate gdb script script.gdb: 9 | 10 | gdb-print-prepare gdb-print-demo.c > script.gdb 11 | 12 | Run the excucutable with gdb and the script: 13 | gdb --batch --quiet --command=script.gdb ./gdb-print 14 | 15 | */ 16 | 17 | int main() 18 | { 19 | //gdb_print(*stdout) 20 | ; 21 | } 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS+=-rdynamic 2 | CXXFLAGS+=-std=c++17 3 | CXXFLAGS+=-g 4 | 5 | e=stack_trace_check tracer-hpp-test 6 | 7 | check: $e ctracer-check 8 | for a in $e; do ./$$a || exit; done 9 | 10 | stack_trace_check: stack_trace.o 11 | 12 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 13 | 14 | obj-m=ctracer-test.o 15 | 16 | ctracer-check: 17 | $(MAKE) -B ctracer-test && ./ctracer-test 18 | make -B -C ${KERNELDIR} modules M=$$PWD && \ 19 | sudo insmod ./ctracer-test.ko && sudo rmmod ctracer-test && dmesg; 20 | $(MAKE) -B ctracer-testpp && ./ctracer-testpp 21 | 22 | clean: 23 | make -B -C ${KERNELDIR} clean M=$$PWD 24 | rm -f stack_trace_check ctracer-test ctracer-testpp tracer-hpp-test 25 | -------------------------------------------------------------------------------- /snippets/str.md: -------------------------------------------------------------------------------- 1 | str - readable string manipulations: ltrim, ltrim-max, rtrim, rtrim-max, subst, subst-all 2 | ==== 3 | 4 | 5 | ``` bash 6 | str() 7 | { 8 | case $1 in 9 | (ltrim) echo "${2#$3}" ;; 10 | (ltrim-max) echo "${2##$3}";; 11 | (rtrim) echo "${2%$3}";; 12 | (rtrim-max) echo "${2%%$3}";; 13 | (subst) echo "${2/$3/$4}";; 14 | (subst-all) echo "${2//$3/$4}";; 15 | (ext) echo "${2#*.}";; 16 | (rtrim-ext) echo "${2%%.*}";; # path without extension 17 | (base) # just filename without path and extension 18 | expr \ 19 | match "$2" '.*/\(.*\)\.tar' \| \ 20 | match "$2" '.*/\(.*\)\.' \| \ 21 | match "$2" '.*/\(.*\)' 22 | ;; 23 | esac 24 | # More: https://www.tldp.org/LDP/abs/html/string-manipulation.html 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /snippets/duplicates.md: -------------------------------------------------------------------------------- 1 | duplicates - finds duplicate files. To follow symbolic links run duplicate -L $DIR 2 | ==== 3 | 4 | 5 | ``` bash 6 | duplicates() 7 | { 8 | # Features: 9 | # * Fast - because it checks sizes first 10 | # and filters same linked files by checking inode (%i) 11 | # * Sorts files by size to help you to delete biggest files first 12 | # 13 | # Troubleshooting: 14 | # on out of memory define TMPDIR 15 | # 16 | set -o noglob 17 | find "$@" $find_exclude -type f \ 18 | -printf "%10i\t%10s\t%p\n" \ 19 | | sort -n \ 20 | | uniq --unique -w10 \ 21 | | cut -f 2,3 | sort -n \ 22 | | uniq --all-repeated -w 10 \ 23 | | cut -f 2 \ 24 | | perl -pe "s/\n/\0/g" \ 25 | | xargs -0 -i{} sha1sum "{}" | sort \ 26 | | uniq --all-repeated=separate -w32 \ 27 | | cut -d ' ' -f 3- 28 | set +o noglob 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /ctracer-testpp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ctracer.h demonstarion and testing 4 | 5 | - Test as user application: 6 | 7 | make -B ctracer-testpp && ./ctracer-testpp 8 | 9 | */ 10 | 11 | 12 | #include "ctracer.h" 13 | #include 14 | 15 | int sub(void) 16 | { _entry:; 17 | return 0; 18 | } 19 | 20 | int main(void) 21 | { _entry:; 22 | int i; 23 | for (i=0; i < 10; i++) 24 | sub(); 25 | trl(); 26 | trvp(i); 27 | trvx(i); 28 | trvd(i); 29 | trvd(sizeof(long long)); 30 | trvd(sizeof(size_t)); 31 | trvd(sizeof(void*)); 32 | trvd(sizeof(int)); 33 | trvd(sizeof(short)); 34 | trvd(sizeof(char)); 35 | if (0) 36 | tracef("Should not be printed\n"); 37 | else 38 | tracef("Should be printed\n"); 39 | if (1) 40 | tracef("Should be printed\n"); 41 | else 42 | tracef("Should not be printed\n"); 43 | 44 | freeram(); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /snippets/gdb-print-prepare.md: -------------------------------------------------------------------------------- 1 | gdb-print-prepare - utility to print C,C++ variables and structs at runtime 2 | ==== 3 | 4 | 5 | ``` bash 6 | gdb-print-prepare() 7 | { 8 | if [[ $# == 0 ]]; then 9 | cat <<-EOF 10 | 11 | Usage: 12 | 13 | Mark print points in C or C++ sources with pseudo comment: 14 | // gdb_print(big_struct) 15 | gdb-print-prepare \$src > app.gdb 16 | gdb --batch --quiet --command=app.gdb \$app 17 | 18 | See file gdb-print-demo.c for example. 19 | 20 | EOF 21 | return 22 | fi 23 | cat <<-EOF 24 | set auto-load safe-path / 25 | EOF 26 | grep --with-filename --line-number --recursive --only-matching 'gdb_print(.*)' $1 | \ 27 | while IFS=$'\t :;()' read file line func var rest; do 28 | cat <<-EOF 29 | break $file:$line 30 | commands 31 | silent 32 | where 1 33 | echo \\n$var\\n 34 | print $var 35 | cont 36 | end 37 | EOF 38 | done 39 | cat <<-EOF 40 | run 41 | echo ---\\n 42 | EOF 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /snippets/doxygen-bootstrap.md: -------------------------------------------------------------------------------- 1 | doxygen-bootstrap - generic handy doxygen wrapper 2 | ==== 3 | 4 | 5 | ``` bash 6 | doxygen-bootstrap() 7 | { 8 | if [ ! -e Doxyfile ]; then 9 | cat > Doxyfile <<-EOF 10 | PROJECT_NAME = "$(basename $PWD)" 11 | EXTRACT_ALL = YES 12 | EXTRACT_STATIC = YES 13 | RECURSIVE = YES 14 | EXCLUDE = html 15 | GENERATE_TREEVIEW = YES 16 | GENERATE_LATEX = NO 17 | HAVE_DOT = YES 18 | DOT_FONTSIZE = 15 19 | CALL_GRAPH = YES 20 | CALLER_GRAPH = YES 21 | INTERACTIVE_SVG = YES 22 | #DOT_TRANSPARENT = YES 23 | DOT_MULTI_TARGETS = NO 24 | DOT_CLEANUP = NO 25 | OPTIMIZE_OUTPUT_FOR_C = YES 26 | DOT_FONTNAME = Ubuntu 27 | #CASE_SENSE_NAMES = YES 28 | SOURCE_BROWSER = YES 29 | QUIET = NO 30 | EOF 31 | # command doxygen -u 32 | fi 33 | cat Doxyfile | doxygen -u - > Doxyfile.explained 34 | cat Doxyfile | doxygen -s -u - > Doxyfile.expanded 35 | command doxygen "$@" 2> doxygen.log 36 | xdg-open html/index.html || firefox html/index.html 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /stack_trace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | extern "C" int stack_trace(void) 14 | { 15 | size_t size; 16 | int i; 17 | void *bt[16]; 18 | 19 | size = backtrace(bt, sizeof(bt)/sizeof(bt[0])); 20 | char **strings = backtrace_symbols(bt, size); 21 | basic_stringstream buff; 22 | for (i = 0; i < size; i++) 23 | cerr << strings[i] << '\n'; 24 | for (i = size - 1; i > -1; i--) { 25 | if (!bt[i]) 26 | break; 27 | string s = strings[i]; 28 | smatch m; 29 | if (!regex_match(s, m, regex(".*\\(([^+]+)\\+.*\\).*"))) { 30 | buff << "> … " ; 31 | continue; 32 | } 33 | char *demangled 34 | = abi::__cxa_demangle(m[1].str().c_str(), 0, 0, 0); 35 | if (demangled) 36 | *strchrnul(demangled, '(') = 0; 37 | else 38 | demangled = strdup(m[1].str().c_str()); 39 | buff << "> " << (demangled?:m[1].str().c_str()) << " "; 40 | free(demangled); 41 | } 42 | buff << "\n"; 43 | cerr << buff.str(); 44 | free(strings); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /tracer-hpp-test.cpp: -------------------------------------------------------------------------------- 1 | // make -B tracer-hpp-test CXXFLAGS=--std=c++17 2 | 3 | #include "tracer.hpp" 4 | #if __cplusplus > 201103 5 | #include 6 | #endif 7 | 8 | using std::string; 9 | 10 | #if __cplusplus >= 201402L 11 | using namespace std::literals::chrono_literals; 12 | #endif 13 | 14 | int main() 15 | { 16 | #if __cplusplus >= 201103 17 | measure_block_duration(); 18 | #endif 19 | int i = -123; 20 | double d = 123.456; 21 | string s = "string value"; 22 | char ca[] = "char array"; 23 | const char * cp = "char pointer"; 24 | void * p = &i; 25 | int * ip = &i; 26 | 27 | #if __cplusplus >= 201402L 28 | std::this_thread::sleep_for(100ms); 29 | #endif 30 | trace(); // prints only file name and line 31 | trace("error:", s); // prints literal message 32 | trace(p); 33 | trace(ip); 34 | trace(cp); 35 | trace(ca); 36 | trace(i, d); 37 | trace(i, s); 38 | trace(i, d, s); 39 | trace(i, d, s, cp); 40 | trace(i, d, s, cp, ca); 41 | trace(i, d, s, cp, ca, i); 42 | trace(i, d, s, cp, ca, i, d); 43 | trace(i, d, s, cp, ca, i, d, s); 44 | // up to 16 variables 45 | trace(i, d, s, cp, ca, i, d, s, i, d, s, cp, ca, i, d, s); 46 | trace(tracer::duration(_block_duration.start)); 47 | trace(s, i); 48 | } 49 | -------------------------------------------------------------------------------- /snippets/load-watch.md: -------------------------------------------------------------------------------- 1 | load-watch - kills memory and cpu hogs when load average is too high 2 | ==== 3 | 4 | 5 | ``` bash 6 | csi=$'\e[' 7 | load-watch() 8 | { 9 | local nproc=$(getconf _NPROCESSORS_ONLN) 10 | echo 11 | while true; do 12 | echo -n ${csi}A 13 | echo -n $(date "+%T $SECONDS ") " " 14 | local load 15 | free=$( grep MemAvailable: /proc/meminfo | (read a b c d e; echo $((b/1024))) ) 16 | IFS="/ " read -a load < /proc/loadavg 17 | local loadproc=$((10#${load/./}00/${nproc}00)) # '10#' is to force decimal, because 'load' starts from 0 18 | local pcpu=$(echo $(ps --no-headers -e -o pid,comm,pcpu --sort -%cpu | head -n 1)) 19 | local pmem=$(echo $(ps --no-headers -e -o pid,comm,pmem --sort -%mem | head -n 1)) 20 | echo -n "load=$load $loadproc% running=${load[3]} free=$free MB, $pcpu% cpu, $pmem% mem" 21 | echo "${csi}K" 22 | test -w /proc/${pcpu%% *}/oom_score_adj && echo 1000 > /proc/${pcpu%% *}/oom_score_adj 23 | test -w /proc/${pmem%% *}/oom_score_adj && echo 1000 > /proc/${pmem%% *}/oom_score_adj 24 | if [ \( ${load[3]} -gt $((1 * ${nproc})) \) -a \( $loadproc -gt 200 \) ]; then 25 | echo killing "${pcpu} " 26 | echo 27 | kill "${pcpu%% *}" 28 | fi 29 | if [ $free -lt 200 ]; then 30 | echo killing "${pmem} " 31 | echo 32 | kill "${pmem%% *}" 33 | fi 34 | SECONDS=0 35 | read -t 5 36 | done 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /ctracer-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ctracer.h demonstarion and testing 4 | 5 | - Test as user application: 6 | 7 | make -B ctracer-test && ./ctracer-test 8 | 9 | - Test as kernel module: 10 | 11 | { KERNELDIR=/lib/modules/$(uname -r)/build; 12 | make -B -C ${KERNELDIR} M=$PWD modules obj-m=ctracer-test.o && 13 | sudo insmod ./ctracer-test.ko && 14 | sudo rmmod ctracer-test && 15 | dmesg; } 16 | 17 | */ 18 | 19 | 20 | #ifdef __KERNEL__ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #else 26 | #include 27 | #endif 28 | 29 | #include "ctracer.h" 30 | 31 | static int sub(void) 32 | { //_entry:; 33 | //_trace_enter(); 34 | _trace_enter_exit_(); 35 | return 0; 36 | } 37 | 38 | int main(void) 39 | { _entry:; 40 | int i; 41 | for (i = 0; i < 10; i++) 42 | sub(); 43 | trl(); 44 | trvp(i); 45 | trvx(i); 46 | trvd(i); 47 | trvd(sizeof(long long)); 48 | trvd(sizeof(size_t)); 49 | trvd(sizeof(void*)); 50 | trvd(sizeof(int)); 51 | trvd(sizeof(short)); 52 | trvd(sizeof(char)); 53 | if (0) 54 | tracef("Should not be printed\n"); 55 | else 56 | tracef("Should be printed\n"); 57 | if (1) 58 | tracef("Should be printed\n"); 59 | else 60 | tracef("Should not be printed\n"); 61 | 62 | freeram(); 63 | return 0; 64 | } 65 | 66 | #ifdef __KERNEL__ 67 | 68 | module_init(main); 69 | 70 | static void mod_exit(void) 71 | { 72 | } 73 | module_exit(mod_exit); 74 | 75 | MODULE_LICENSE("GPL"); 76 | #endif 77 | -------------------------------------------------------------------------------- /instrument-tracer.cc: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief Instrumental tracing utility. 4 | Copyright (C) 2021 Constantine Shulyupin 5 | 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | using namespace std; 15 | using namespace filesystem; 16 | 17 | /** 18 | 19 | Usage. 20 | 21 | Add to Makefile or equivalent: 22 | 23 | CXXFLAGS+=-rdynamic -finstrument-functions -finstrument-functions-exclude-file-list=/usr/include/,instrument-tracer.cc -finstrument-functions-exclude-function-list=basic_regex 24 | LDLIBS+=-ldl 25 | instrument-tracer.o: CXXFLAGS+=-std=c++17 26 | 27 | */ 28 | 29 | __attribute__((no_instrument_function)) 30 | string demangle(const char * name) 31 | { 32 | if (!name) 33 | return "-"; 34 | unique_ptr cn{abi::__cxa_demangle(name, 0, 0, 0), free}; 35 | 36 | if (!cn) 37 | return name; 38 | // truncate arguments and tags from signature 39 | *strchrnul(cn.get(), '(') = 0; 40 | *strchrnul(cn.get(), '[') = 0; 41 | return cn.get(); 42 | } 43 | 44 | static thread_local atomic_int level; 45 | 46 | __attribute__((no_instrument_function)) 47 | string addr2line(const char *name, int addr) 48 | { 49 | static map cache; 50 | if (cache.count(addr)) 51 | return cache[addr]; 52 | 53 | char buf[200] = ""; 54 | char * bufp = buf; 55 | 56 | stringstream hs; 57 | hs << hex << addr; 58 | string cmd = string("addr2line -e ") + name + " " + hs.str(); 59 | unique_ptr f{popen(cmd.c_str(), "r"), pclose}; 60 | 61 | if (!f) 62 | return ""; 63 | 64 | auto s = fgets(buf, sizeof(buf), f.get()); 65 | if (s) { 66 | s[strlen(s) - 1] = ':'; 67 | // TODO: remove canonical(absolute(current_path())) 68 | if (strrchr(s, '/')) 69 | bufp = strrchr(s, '/') +1; 70 | } 71 | cache[addr] = bufp; // store even empty string 72 | return bufp; 73 | } 74 | 75 | __attribute__((no_instrument_function)) 76 | void trace_enter_exit(void *caller, char dir, void *func) 77 | { 78 | #if 0 79 | void *bt[4]; 80 | backtrace(bt, 4); 81 | char **strings = backtrace_symbols(bt, 4); 82 | for (int i = 2; i < (int)4; i++) 83 | trvs(strings[i]); 84 | free(strings); 85 | #endif 86 | Dl_info ci, fi = {}; 87 | dladdr(func, &fi); 88 | dladdr(caller, &ci); 89 | if (!fi.dli_sname) 90 | return; 91 | 92 | string n = demangle(fi.dli_sname); 93 | 94 | string line = addr2line((char*)fi.dli_saddr - (char*)fi.dli_fbase); 95 | stringstream out; 96 | auto tid = this_thread::get_id(); 97 | static map threads; 98 | if (!threads.count(tid)) 99 | threads[tid] = threads.size(); 100 | 101 | static thread::id prev_tid; 102 | if (prev_tid != tid) { 103 | out << line << " thread " << threads[tid] << ":" << endl; 104 | prev_tid = tid; 105 | } 106 | out << line << ' ' << string(level, '\t') << n ; 107 | out << endl; 108 | cerr << out.str(); 109 | #if 0 110 | cerr << canonical(absolute(program_invocation_name)).string() << endl; 111 | trace(); 112 | trace(canonical(program_invocation_name).string()); 113 | trace(absolute(program_invocation_name).string()); 114 | trace(canonical(absolute(program_invocation_name)).string()); 115 | trace(canonical(absolute(current_path())).string()); 116 | exit(0); 117 | #endif 118 | } 119 | 120 | extern "C" 121 | __attribute__((no_instrument_function)) 122 | void __cyg_profile_func_enter(void *func, void *caller) 123 | { 124 | trace_enter_exit(caller, '>', func); 125 | ++level; 126 | } 127 | 128 | extern "C" 129 | __attribute__((no_instrument_function)) 130 | void __cyg_profile_func_exit( void *func, void *caller ) 131 | { 132 | trace_enter_exit(caller, '<', func); 133 | --level; 134 | } 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lib.sh - Library of shell functions 2 | === 3 | Usage: 4 | 5 | Load commands to shell: 6 | * . lib.sh 7 | 8 | Run a command with subshell: 9 | * lib.sh \ \ 10 | * lib_help - shows help for Lib.sh 11 | 12 | List of available commands: 13 | * ps-all - lists all processes 14 | * ps-threads - lists processes with threads 15 | * ps-tree - lists process tree via ps, see also pstree -p 16 | * ps-cpu - lists most CPU consuming processes 17 | * ps-mem - lists most memory consuming processes 18 | * default-eth - provides default Ethernet interface 19 | * external-ip - Provides external IP 20 | * ps-wchan - shows what processes are waiting for, used in debugging blocked processes 21 | * ls-size - list files with sizes in bytes, shorter than ls -l 22 | * mplayer-rotate-right - play video rotated right, used to play vertically captured videos 23 | * hist - handy history, up to one screen length 24 | * deb-list - list content of specified deb file 25 | * quotation-highlight - highlight text in quotation marks ("quotation") 26 | * keyboard-shortcuts - bash keyboard shortcuts. See also man readline. 27 | * tcpdump-text - tcpdump of payload in text 28 | * make-debug - verbose make 29 | * git-diff - handy git diff 30 | * git-prompt - sets shell prompt to show git branch 31 | * git-fixup - interactive fix up of specified number of last git commits 32 | * git-ign-add - add files' names with path to appropriate .gitignore list 33 | * log - safely prints messages to stderr 34 | * trap-err - traps command failures, print return value and returns, better than set -o errexit 35 | * system-status-short - shows short summary of system resources (RAM,CPU) usage 36 | * system-status-long - shows long system status and statistics by running various system utilities 37 | * shell-type - tries to identify type of current shell 38 | * ps-of - specified process info 39 | * proc-mem-usage - returns percentage memory usage by specified process 40 | * dir-diff - compare listings of two specified directories 41 | * retry - retry argument operation till success 42 | * duplicates - finds duplicate files. To follow symbolic links run duplicate -L $DIR 43 | * for-each - applies an operation to set of arguments one by one 44 | * str - readable string manipulations: ltrim, ltrim-max, rtrim, rtrim-max, subst, subst-all 45 | * postfix-extract - return filename postfix: path/name[-_]postfix.ext -> postfix 46 | * unzip-dir - handy unzip to directory with name of zip-file 47 | * mac-to-ip - looks for LAN IP for MAC 48 | * ip-to-mac - show MAC address for specified IP in LAN 49 | * fs-usage - show biggest directories and optionally files on a filesystem, for example on root: fs-usage -a / 50 | * PATH-append - prints PATH in readable format 51 | * PATH-insert - inserts argument to head of PATH, if required 52 | * PATH-remove - removes argument from PATH 53 | * PATH-append - prints PATH in readable format 54 | * gcc-set - set specified [cross] compiler as default in environment 55 | * gcc-set - set specified [cross] compiler as default in environment 56 | * get-source - download and unpack an open source tarball 57 | * get-source - download and unpack an open source tarball 58 | * gnu-build - universal complete build and install of gnu package 59 | * alternative-config-build - build of package, alternatively to gnu-build 60 | * build-env - configure staging build environment 61 | * glib-arm-build - demonstration of arm compilation of glib from the scratch 62 | * staging-dir-fix - fix parameter libdir in *.la files in staging cross-compilation directory 63 | * mem-drop-caches - drop caches and free this memory. Practically not required 64 | * gdb-print-prepare - prepares gdb script to print variables and structs at runtime 65 | * wget-as-me - Run wget with cookies from firefox to access authenticated data 66 | * calc - calculate with bc specified floating point expression 67 | * md5sum-make - create md5 files for each specified file separately 68 | * check - runs verbosely specified command and prints return status 69 | * lib-sh-demo - run lib.sh functions for demonstration and testing 70 | * doxygen-bootstrap - generic handy doxygen wrapper 71 | * load-watch - kills memory and cpu hogs when load average is too high 72 | * dts-tags - extacts tags (ctags format)from device tree source files 73 | -------------------------------------------------------------------------------- /tracer.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 2 | * Copyright (C) 2019 Constantine Shulyupin 3 | * Original: https://gitlab.com/makelinux/lib/blob/master/tracer.hpp 4 | */ 5 | 6 | #pragma once 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #if __cplusplus >= 201103 13 | #include 14 | #endif 15 | 16 | /** \cond */ 17 | 18 | #ifndef __file__ 19 | #define ctracer_cut_path(fn) (fn[0] != '/' ? fn : (strrchr(fn, '/') + 1)) 20 | #define __file__ ctracer_cut_path(__FILE__) 21 | #endif 22 | 23 | #define file_line() (std::string(__file__) + ":" + std::to_string(__LINE__) + ": " + __func__ + " ") 24 | 25 | #define _strlen(s) std::char_traits::length(s) 26 | 27 | namespace tracer 28 | { 29 | 30 | static inline const std::string to_string() {return "";} 31 | static inline const std::string to_string(const std::string &s) {return '"' + s + '"';} 32 | 33 | static inline const std::string to_string(void * const p) {std::stringstream s; s << p; return s.str();} 34 | 35 | // for char * 36 | static inline const std::string to_string(const char * c) {return '"' + std::string(c) + '"';} 37 | 38 | // for const char x[] 39 | static inline const std::string to_string(char * const c) {return '"' + std::string(c) + '"';} 40 | 41 | #if __cplusplus >= 201103 42 | template 43 | static inline const std::string to_string(const T &s) {return std::to_string(s);} 44 | #endif 45 | 46 | template 47 | static inline const std::string to_string(T * const p) {return to_string((void *)p);} 48 | 49 | #ifndef log_str 50 | #define log_str(a) do { std::cerr << a << std::endl; } while (0) 51 | #endif 52 | 53 | #ifdef __cpp_if_constexpr 54 | #define _IF(x) if constexpr (x) 55 | #else 56 | #define _IF(x) if (x) 57 | #endif 58 | 59 | // prints name=value or just raw value for literal strings 60 | #define _v(a) ({auto as = tracer::to_string(a); _strlen(#a) ? \ 61 | /* if it is literal */ \ 62 | (as == #a) ? \ 63 | /* Assuming string literal within '"'. */ \ 64 | /* Getting just content of string literal. */ \ 65 | std::string(#a).substr(1, std::string(#a).length() - 2) + " " \ 66 | /* else */ \ 67 | : std::string(#a) + "=" + as + " " : ""; }) 68 | 69 | #define _trace2(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) s << _v(args); } while (0) 70 | #define _trace3(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace2(s, args); } while (0) 71 | #define _trace4(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace3(s, args); } while (0) 72 | #define _trace5(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace4(s, args); } while (0) 73 | #define _trace6(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace5(s, args); } while (0) 74 | #define _trace7(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace6(s, args); } while (0) 75 | #define _trace8(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace7(s, args); } while (0) 76 | #define _trace9(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace8(s, args); } while (0) 77 | #define _traceA(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace9(s, args); } while (0) 78 | #define _traceB(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceA(s, args); } while (0) 79 | #define _traceC(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceB(s, args); } while (0) 80 | #define _traceD(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceC(s, args); } while (0) 81 | #define _traceE(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceD(s, args); } while (0) 82 | #define _traceF(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceE(s, args); } while (0) 83 | 84 | /** \endcond */ 85 | 86 | /** 87 | * \brief Universal C++ tracing function 88 | * 89 | * Accepts from none to 16 arguments. 90 | * Prints file and line number, arguments names and values. 91 | * 92 | * Example source code: 93 | * trace(i, s); 94 | * 95 | * Output: 96 | * tracer-hpp-test.cpp:33:main i=-123 s="string value" 97 | * 98 | * See file tracer-hpp-test.cpp for more examples. 99 | */ 100 | 101 | #define trace(a, args...) \ 102 | do { std::stringstream log; \ 103 | log << file_line() << _v(a); \ 104 | _IF(!!_strlen(#args)) \ 105 | _traceF(log, args); \ 106 | log_str(log.str()); \ 107 | } while (0) 108 | 109 | #if __cplusplus >= 201103 110 | static inline double duration(std::chrono::time_point start) 111 | { 112 | return std::chrono::duration {std::chrono::steady_clock::now() - start}.count(); 113 | } 114 | 115 | struct _duration { 116 | std::chrono::time_point start; 117 | std::string file_line; 118 | explicit _duration(std::string fl) { file_line = fl; start = std::chrono::steady_clock::now(); } 119 | ~_duration() {log_str(file_line + "duration = " + to_string(duration(start)));} 120 | }; 121 | 122 | #define measure_block_duration() tracer::_duration _block_duration(file_line()); 123 | #endif 124 | } // namespace tracer 125 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from sys import * 5 | from os.path import * 6 | from netifaces import * 7 | from munch import * 8 | from pprint import * 9 | from sys import * 10 | from inspect import * 11 | import inspect 12 | import types 13 | import pyiface 14 | from pyiface.ifreqioctls import IFF_UP, IFF_RUNNING 15 | from collections import defaultdict 16 | from bs4 import BeautifulSoup 17 | import datetime 18 | import signal 19 | 20 | 21 | 22 | def net_info(): 23 | ''' 24 | Gives basic networking info like local IP 25 | ''' 26 | net = Munch() 27 | net.interfaces = dict() 28 | net.def_if = interfaces()[1] 29 | try: 30 | net.def_if = gateways()['default'][AF_INET][1] 31 | except KeyError: 32 | pass 33 | 34 | try: 35 | net.ip = ifaddresses(net.def_if)[AF_INET][0]['addr'] 36 | net.def_mac = ifaddresses(net.def_if)[AF_PACKET][0]['addr'] 37 | except KeyError: 38 | pass 39 | 40 | #s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 41 | #n = s.fileno() 42 | #ifr = ifreq() 43 | #ifr.ifr_ifrn = "lo".encode('utf-8') 44 | #fcntl.ioctl(n, SIOCGIFFLAGS, ifr); 45 | #print("SIOCGIFFLAGS", ifr.ifr_flags); 46 | net.ifs = " ".join(interfaces()) 47 | for i in interfaces(): 48 | ifd = Munch() 49 | flags = pyiface.Interface(name=i).flags 50 | #net.flags = defaultdict(lambda: Munch()) 51 | if flags & IFF_UP > 0: 52 | ifd.flags = "U" 53 | if flags & IFF_RUNNING > 0: 54 | ifd.flags += "R" 55 | try: 56 | ifd.addr= ifaddresses(i)[AF_INET][0]['addr'] 57 | except KeyError: 58 | pass 59 | net.interfaces[i] = dict(ifd) 60 | return dict(net) 61 | 62 | 63 | def repeated_gray(): 64 | ''' 65 | Filters input text and prints in gray color lines which was already before 66 | ''' 67 | passed = {} 68 | for l in stdin: 69 | l = l.rstrip() 70 | if l in passed: 71 | print('\033[37m%s\033[30m' % (l)) 72 | else: 73 | print(l) 74 | passed[l] = True 75 | 76 | def info_gray(): 77 | ''' 78 | Filters input text and prints in gray color info lines 79 | ''' 80 | passed = {} 81 | for l in stdin: 82 | l = l.rstrip() 83 | e = l.find('=ERR=') 84 | if e != -1: 85 | print(l[:e] + '\033[1;38m=ERR=\033[0m' + l[e+5:]) 86 | elif 'INFO' in l: 87 | print('\033[2;30m%s\033[0m' % (l)) 88 | else: 89 | print(l) 90 | 91 | 92 | import pandas as pd 93 | 94 | def wikitable_transpose(): 95 | T = [[]] 96 | i = j = 0; 97 | for l in stdin: 98 | l = l.rstrip() 99 | if l == '|}': 100 | for r in T: 101 | for c in r: 102 | print(c) 103 | print('|-') 104 | elif l[0] in ('|', '!') and (len(l) == 1 or l[1] not in ('+', '-')): 105 | i += 1; 106 | if i + 1 > len(T): 107 | T.append([0]) 108 | if j + 1 > len(T[i]): 109 | T[i].append(0) 110 | T[i][j] = l 111 | continue 112 | elif l == '|-': 113 | j += 1 114 | i = 0; 115 | continue 116 | print(l) 117 | 118 | 119 | def commonprefix_gray(): 120 | ''' 121 | Filters input text and prints in gray color start of current line which is same like previous 122 | ''' 123 | p = '' 124 | pcl = 0 125 | for l in stdin: 126 | l = l.rstrip() 127 | c = commonprefix([p, l]) 128 | cl = len(c) 129 | print('\033[2;36m' + l[:cl] + '\033[0;30m' + l[cl:]) 130 | if False: 131 | if cl < pcl: 132 | print(l) 133 | else: 134 | print('\033[37m' + '·' * cl + '\033[30m' + l[cl:]) 135 | p = l 136 | pcl = cl 137 | 138 | if __name__ == "__main__": 139 | def handler(signum, frame): 140 | exit(0) 141 | 142 | signal.signal(signal.SIGHUP, handler) 143 | try: 144 | ret = 0 145 | if len(argv) > 1: 146 | a1 = argv[1] 147 | argv = argv[1:] 148 | if '(' in a1: 149 | ret = eval(a1) 150 | else: 151 | ret = eval(a1 + '(' + ', '.join("'%s'" % (a) 152 | for a in argv[1:]) + ')') 153 | pprint(ret) if ret else 0 154 | else: 155 | for m in getmembers(modules[__name__]): 156 | if isfunction(m[1]) and m[1].__module__ == __name__: 157 | help(m[1]) 158 | if isinstance(ret, type(False)) and ret == False: 159 | exit(os.EX_CONFIG) 160 | #except KeyboardInterrupt: 161 | except Exception as inst: 162 | print(type(inst)) # the exception instance 163 | print(inst.args) # arguments stored in .args 164 | print(inst) 165 | warning("\nInterrupted") 166 | -------------------------------------------------------------------------------- /ctracer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | Tracing utility for C 4 | 5 | implemented in single h-file 6 | 7 | Original source: 8 | https://gitlab.com/makelinux/ldt/blob/master/ctracer.h 9 | 10 | Copyright (C) 2012 Constantine Shulyupin http://www.makelinux.net/ 11 | 12 | Dual BSD/GPL License 13 | */ 14 | #ifndef __cplusplus 15 | #pragma GCC diagnostic ignored "-Wdeclaration-after-statement" 16 | #endif 17 | #pragma GCC diagnostic ignored "-Wunused-label" 18 | 19 | #if 0 20 | /* Optional configuration flags: */ 21 | #define TRACE_TIME 22 | #define TRACE_MALLOC 23 | #define TRACE_LINUX_MEMORY_ON 24 | #endif 25 | /* 26 | Usages: 27 | 28 | cmake -DCMAKE_CXX_FLAGS='-include ctracer.h' 29 | 30 | make CXX_FLAGS='-include ctracer.h' VERBOSE=1 31 | 32 | 33 | VI command to include label _entry to each function start for tracing 34 | 35 | :%s-) *\n{ *$-)\r{\t_entry:;- 36 | :%s-\(return ret;\)-do {trlm("return");\1} while (0)- 37 | :%s-return \(.*\);-do {trlm("\1");return \1;} while (0);-g 38 | :%s-goto \(.*\);-do {trlm("\1");goto \1;} while (0);-g 39 | 40 | 41 | sed -i '\-)-{ N; s-)\([\r\n]\+\){$-)\1{\t_entry:;- }' 42 | 43 | Trace return error: 44 | :%s-return -\(E\w*\);-{trlm("\1");return -\1;} 45 | 46 | remove: 47 | sed -i 's-{\t_entry:;-{-' $(grep -lr $'^{\t_entry:' .) 48 | 49 | */ 50 | 51 | #ifndef __ASSEMBLY__ 52 | 53 | #ifndef CTRACER_H_INCLUDED 54 | #define CTRACER_H_INCLUDED 55 | extern __thread int ctracer_ret; 56 | 57 | #define multistatement(ms) ms /* trick to bypass checkpatch.pl error */ 58 | 59 | #ifndef CTRACER_OFF 60 | 61 | //#define _entry multistatement(trllog(); goto _entry; _entry) 62 | //#define _entry multistatement(_trace_enter(); goto _entry; _entry) 63 | 64 | 65 | #define _entry multistatement(_trace_enter_exit_(); \ 66 | goto _entry_second; _entry_second) 67 | 68 | //#define _entry once(trl()); goto _entry; _entry 69 | /* 70 | #define return trlm("} "); return 71 | */ 72 | #else 73 | #define _entry multistatement(goto _entry_second; _entry_second) 74 | #endif 75 | 76 | #define do_statement(a) do { a } while (0) 77 | 78 | /* 79 | trace variables: integer, hex, string, pointer, float, time value 80 | macro with '_' doesn't prints new line 81 | notation: 82 | tr = trace 83 | v = printf Variable in specified format (d, x, f, s, etc) 84 | */ 85 | 86 | #define trla(fmt, args...) tracef("%s:%i: %s " fmt, __file__, __LINE__, __func__, ## args) 87 | #define trv(t, v) tracef(#v " = %" t EOL, v) 88 | #define trv_(t, v) tracef(#v " = %" t " ", v) 89 | #define trvd(d) tracef(#d " = %ld" EOL, (long int)(d)) 90 | #define trvd_(d) tracef(#d " = %ld ", (long int)(d)) 91 | #define trvx_(x) tracef(#x " = 0x%lx ", (long int)(x)) 92 | #define trvx(x) tracef(#x " = 0x%lx" EOL, (long int)(x)) 93 | #define trvlx(x) tracef(#x " = %#llx" EOL, (long long)(x)) 94 | #define trvf(f) tracef(#f " = %g" EOL, f) 95 | #define trvf_(f) tracef(#f " = %g ", f) 96 | #define trvtv_(tv) tracef(#tv" = %u.%06u ", (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec) 97 | #define trvtv(tv) tracef(#tv " = %u.%06u" EOL, (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec) 98 | #define trvs(s) tracef(#s " = \"%s\"" EOL, (char*)s) 99 | #define trvs_(s) tracef(#s" = \"%s\" ", (char*)s) 100 | #define trvp(p) tracef(#p " = %016zx" EOL, (size_t)p) 101 | #define trvp_(p) tracef(#p" = %016zx ", (size_t)p) 102 | #define trvdn(d, n) {int i; tracef("%s", #d"[]="); \ 103 | for (i = 0; i < n; i++) tracef("%d:%d,", i, (*((int *)d+i))); tracef(EOL); } 104 | #define trvxn(d, n) {int i; tracef("%s", #d"[]="); \ 105 | for (i = 0; i < n; i++) tracef("%04x,", (*((int *)d+i))); tracef(EOL); } 106 | #define trvdr(record) trvdn(&record, sizeof(record)/sizeof(int)) 107 | #define trvxr(record) trvxn(&record, sizeof(record)/sizeof(int)) 108 | 109 | /* trvdnz - TRace Digital Variable, if Not Zero */ 110 | #define trvdnz(d) { if (d) tracef(#d " = %d" EOL, (int)(d)); } 111 | #define trace_call(a) do { trla("calling %s {\n", #a); a; tracef("} done\n"); } while (0) 112 | 113 | /* trlm - TRace Location, with Message */ 114 | #define trlm(m) tracef("%s:%i: %s %s" EOL, __file__, __LINE__, __func__, m) 115 | #define trlm_(m) tracef("%s:%i: %s %s ", __file__, __LINE__, __func__, m) 116 | #define trl() do { trace_time(); trlm(""); } while (0) 117 | #define trl_() tracef("%s:%i: %s ", __file__, __LINE__, __func__) 118 | #define trln() tracef(EOL) 119 | 120 | #define trlvd(d) tracef("%s:%d: %s %s=%ld\n", __file__, __LINE__, __func__, #d, (long)(d)) 121 | #define trlvx(x) tracef("%s:%d: %s %s=0x%lx\n", __file__, __LINE__, __func__, #x, (long)(x)) 122 | 123 | #define trl_in() do_statement(trace_time(); trlm("{");) 124 | #define trl_out() do_statement(trace_time(); trlm("}");) 125 | #define empty_statement() do { } while (0) 126 | 127 | #define trace_mem(P, N) \ 128 | IFTRACE({ int i = 0; tracef("%s=", #P); for (; i < (int)(N) ; i++) \ 129 | { if (i && (!(i % 16))) tracef("%i:", i); \ 130 | tracef("%02x ", 0xFF & *((char *)((void *)(P))+i)); \ 131 | if (!((i+1) % 4)) \ 132 | tracef(" "); \ 133 | if (!((i+1) % 16)) \ 134 | tracef(EOL); \ 135 | }; tracef(EOL); }) 136 | 137 | #define trace_mem_int_list(P, N) \ 138 | IFTRACE({ int i = 0; for (; i < (int)(N); i += sizeof(int)) \ 139 | { tracef("%i, ", *(int *)((void *)(P)+i)); \ 140 | }; }) 141 | 142 | #define trace_mem_int(P, N) \ 143 | IFTRACE({ int i = 0; for (; i < (int)(N) ; i += sizeof(int)) \ 144 | { if (i && (!(i % 16))) tracef("%i:", i); \ 145 | tracef("%x ", *(int *)((void *)(P)+i)); \ 146 | if (!((i+1) % 64)) \ 147 | tracef(EOL); \ 148 | }; tracef(EOL); }) 149 | 150 | #define trace_ioctl(nr) tracef("ioctl=(%c%c %c #%i %i)\n", \ 151 | (_IOC_READ & _IOC_DIR(nr)) ? 'r' : ' ', (_IOC_WRITE & _IOC_DIR(nr)) ? 'w' : ' ', \ 152 | _IOC_TYPE(nr), _IOC_NR(nr), _IOC_SIZE(nr)) 153 | 154 | #define trace_ioctl_(nr) tracef("ioctl=(%i %i %i %i)", _IOC_DIR(nr), _IOC_TYPE(nr), _IOC_NR(nr), _IOC_SIZE(nr)) 155 | 156 | #define chkz(a) \ 157 | (p = a,\ 158 | ((!p) ? tracef("%s %i %s FAIL %i = %s\n", __file__, __LINE__, __func__, p, #a) : 0),\ 159 | p) 160 | 161 | #define chkn(a) \ 162 | (ctracer_ret = a,\ 163 | ((ctracer_ret < 0) ? tracef("%s:%i: %s FAIL\n\t%i=%s\n", __file__, __LINE__, __func__, ctracer_ret, #a)\ 164 | : 0), ctracer_ret) 165 | 166 | #define chkne(a) \ 167 | (/* tracef("calling %s\n",#a), */ \ 168 | ctracer_ret = a,\ 169 | ((ctracer_ret < 0) ? tracef("%s:%i: %s FAIL errno = %i \"%s\" %i = %s\n", __file__, __LINE__, __func__, \ 170 | errno, strerror(errno), ctracer_ret, #a)\ 171 | : 0), ctracer_ret) 172 | 173 | #define chkn2(a) \ 174 | (ctracer_ret = a,\ 175 | ((ctracer_ret < 0) ? tracef("%s %i %s FAIL %i = %s\n", __file__, __LINE__, __func__, ctracer_ret, #a)\ 176 | : tracef("%s %i %s %i = %s\n", __file__, __LINE__, __func__, ctracer_ret, #a)),\ 177 | ctracer_ret) 178 | 179 | #ifndef once 180 | #define once(exp) do_statement( \ 181 | static int _passed; if (!_passed) {exp; }; _passed = 1;) 182 | #endif 183 | 184 | 185 | #ifndef CTRACER_OFF 186 | #define IFTRACE(x) x 187 | 188 | #ifdef __KERNEL__ 189 | 190 | #ifdef with_trace_noise 191 | #include 192 | #include 193 | 194 | struct trace_data { 195 | u64 start; 196 | const char *func; 197 | void *arg; 198 | }; 199 | 200 | static inline void __trace_noise_on_cleanup(struct trace_data *td) 201 | { 202 | trace_noise(td->func, td->arg, sched_clock() - td->start); 203 | } 204 | 205 | #define func_trace_noise() struct trace_data __attribute__((cleanup(__trace_noise_on_cleanup))) td = {start:sched_clock(), func:__func__}; 206 | #endif 207 | 208 | #ifdef stack_trace 209 | #include 210 | #endif 211 | #ifndef _LINUX_VMALLOC_H 212 | extern void vfree(const void *addr); 213 | #endif 214 | //#define malloc(s) vmalloc(s) 215 | //#define free(p) vfree(p) 216 | #undef TRACE_TIME 217 | #ifndef printk_ratelimit 218 | #include 219 | #include 220 | #endif 221 | 222 | #ifdef TRACE_LINUX_MEMORY_ON 223 | #include 224 | #undef pr_fmt 225 | 226 | extern int free_pages_prev; 227 | #define trace_linux_mem() do { \ 228 | extern zone_t *zone_table[MAX_NR_ZONES*MAX_NR_NODES]; \ 229 | int mem_change = zone_table[0]->free_pages - free_pages_prev; \ 230 | if (mem_change) { \ 231 | trl_(); trvi_(mem_change); trvd(zone_table[0]->free_pages); } \ 232 | free_pages_prev = zone_table[0]->free_pages; \ 233 | } while (0) 234 | #endif 235 | 236 | 237 | 238 | #define tracef(fmt, args...) printk(fmt, ##args) 239 | 240 | #else /* !__KERNEL__ */ 241 | /* !CTRACER_OFF and not __KERNEL__ */ 242 | #define si_meminfo sysinfo 243 | #include 244 | #define tracef(fmt, args...) ({ flockfile(stderr); fprintf(stderr, fmt, ##args); funlockfile(stderr);}) 245 | 246 | #if 0 247 | #include 248 | #define BP {trl(); kill(0, SIGTRAP); } 249 | #define BP kill(0, SIGTRAP) 250 | #endif 251 | 252 | #endif /* !__KERNEL__ */ 253 | 254 | #ifndef _hweight32 255 | static inline unsigned int _hweight32(unsigned int w) 256 | { 257 | /* from kernel */ 258 | w -= (w >> 1) & 0x55555555; 259 | w = (w & 0x33333333) + ((w >> 2) & 0x33333333); 260 | w = (w + (w >> 4)) & 0x0f0f0f0f; 261 | return (w * 0x01010101) >> 24; 262 | } 263 | 264 | #define _hweight32 _hweight32 265 | #endif 266 | #define trllog() \ 267 | do { \ 268 | static int num; \ 269 | if (_hweight32(num) < 2) { \ 270 | trla("#%d\n", (int)num); \ 271 | } num++; \ 272 | } while (0) 273 | 274 | #define trleach(n, args ...) \ 275 | do { \ 276 | static int num; \ 277 | if (!(num % n)) { \ 278 | trl_(); \ 279 | trvi_(num); \ 280 | args; \ 281 | trln(); \ 282 | } num++; \ 283 | } while (0) 284 | 285 | #else /* CTRACER_OFF */ 286 | #define trllog() 287 | 288 | static inline int empty_function(void) 289 | { 290 | return 0; 291 | } 292 | 293 | #define IFTRACE(x) empty_statement() 294 | #define trace_linux_mem() empty_statement() 295 | #define tracef(fmt, args...) empty_function() 296 | #define stack_trace() empty_statement() 297 | 298 | #endif /* _TARCE */ 299 | 300 | #define EOL "\n" /* for console */ 301 | 302 | //#ifdef MODULE 303 | #if 1 304 | /* omit full absolute path for modules */ 305 | #ifdef __GNUG__ 306 | #include 307 | #else 308 | extern char *strrchr(const char *s, int c); 309 | #endif 310 | #define ctracer_cut_path(fn) (!strrchr(fn, '/') ? fn : (strrchr(fn, '/') + 1)) 311 | #define __file__ ctracer_cut_path(__FILE__) 312 | #else 313 | #define __file__ __FILE__ 314 | #endif 315 | 316 | #ifdef TRACE_MALLOC 317 | static int malloc_count; 318 | static void *malloc_trace; 319 | #endif 320 | #ifdef TRACE_MALLOC 321 | 322 | #define malloc(s) \ 323 | (trla("malloc #%i %p %i\n", ++malloc_count, malloc_trace = malloc(s), s),\ 324 | malloc_trace) 325 | 326 | #define free(p) { free(p); trla("free #%i %p\n", malloc_count--, (void *)p); } 327 | 328 | #define strdup(s) \ 329 | (trla("strdup #%i %p\n", ++malloc_count, malloc_trace = (void *)strdup(s)),\ 330 | (char *)malloc_trace) 331 | 332 | #endif 333 | 334 | #ifdef TRACE_TIME 335 | 336 | #include 337 | #include 338 | 339 | #ifndef trace_time_defined 340 | #define trace_time_defined 341 | 342 | void trace_time(void); 343 | /* 344 | extern double time_prev_f; 345 | void static inline trace_time() 346 | { 347 | time_t time_cur; 348 | double time_cur_f; 349 | time(&time_cur); 350 | struct timeval tv; 351 | struct timezone tz; 352 | struct tm* time_tm; 353 | gettimeofday(&tv, &tz); 354 | time_tm = localtime(&time_cur); 355 | time_cur = tv.tv_sec; 356 | time_cur_f = 0.000001 * tv.tv_usec + time_cur; 357 | double passed = time_cur_f - time_prev_f; 358 | if (passed > 0.001) 359 | { 360 | tracef("time=%04d-%02d-%02d %02d:%02d:%02d %02d +%1.4f s\n", 361 | time_tm->tm_year+1900, time_tm->tm_mon+1, time_tm->tm_mday, 362 | time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec, (int)tv.tv_usec, 363 | passed); 364 | time_prev_f = time_cur_f; 365 | } 366 | } 367 | */ 368 | #endif 369 | 370 | #else 371 | #define trace_time() empty_statement() 372 | #endif 373 | 374 | #ifdef __GLIBC__ 375 | #include 376 | #include 377 | #include 378 | #ifndef _GNU_SOURCE 379 | #define _GNU_SOURCE 380 | #endif 381 | #include 382 | 383 | #ifdef stack_trace 384 | #undef stack_trace 385 | #endif 386 | #ifndef stack_trace_difined 387 | #define stack_trace_difined 388 | /* only once */ 389 | static inline void stack_trace(void) 390 | { 391 | void *array[5]; 392 | char **strings; 393 | int i; 394 | int size = backtrace(array, sizeof(array) / sizeof(array[0])); 395 | strings = backtrace_symbols(array, size); 396 | tracef("Stack:\n"); 397 | 398 | for (i = 0; i < size; i++) { 399 | if (!array[i]) 400 | break; 401 | tracef("%d %p %s\n", i, array[i], strings[i]); 402 | } 403 | //vfree(strings); 404 | free(strings); 405 | } 406 | #endif 407 | #endif /* __GLIBC__ */ 408 | 409 | /* see also nr_free_pages */ 410 | #define freeram() { \ 411 | static size_t last; struct sysinfo i; si_meminfo(&i); trl_(); \ 412 | unsigned long d = last-i.freeram; size_t used = i.totalram-i.freeram; \ 413 | trvd_(i.freeram); trvd_(used); trvd(d); \ 414 | last = i.freeram; } 415 | 416 | extern int sprint_symbol_no_offset(char *buffer, unsigned long address); 417 | 418 | #ifndef CTRACER_OFF 419 | static inline void __on_cleanup(char (*s)[512]) 420 | { 421 | if (*s) 422 | tracef("%s" EOL, *s); 423 | } 424 | 425 | #define _CTRACRE_BUF_LEN 512 426 | 427 | #ifdef __GLIBC__ 428 | #ifndef strsep 429 | char *strsep(char **stringp, const char *delim); 430 | #endif 431 | static inline int lookup_symbol_name(unsigned long addr, char *symbol) 432 | { 433 | char **strings; 434 | strings = backtrace_symbols((void * const*)&addr, 1); 435 | int r; 436 | // printk("%pf", symbol); 437 | if (strings && strings[0]) { 438 | //char *s = strchr(strings[0],'(') + 1; 439 | //if (s) s+=1; else 440 | 441 | char *s = strings[0]; 442 | char *w1 = strsep(&s, " (+)"); 443 | char *w2 = strsep(&s, " (+)"); 444 | r = snprintf(symbol, _CTRACRE_BUF_LEN, "%s", w2 && *w2 ? w2 : w1); 445 | } else 446 | r = snprintf(symbol, _CTRACRE_BUF_LEN, "%lx", addr); 447 | free(strings); 448 | return r; 449 | } 450 | #endif 451 | #ifdef MODULE 452 | /* func lookup_symbol_name is defined in the kernel but is not 453 | exported to be used in modules 454 | */ 455 | static inline int lookup_symbol_name(unsigned long addr, char *symbol) 456 | { 457 | return snprintf(symbol, _CTRACRE_BUF_LEN, "%016lX", addr); 458 | } 459 | #endif 460 | #if defined(__KERNEL__) 461 | #define malloc(s) vmalloc(s) 462 | #endif 463 | #define _trace_enter_exit_() \ 464 | char __attribute__((cleanup(__on_cleanup))) _ret_msg[512]; \ 465 | static int _trace_enter_num; _trace_enter_num++; \ 466 | { char _caller[_CTRACRE_BUF_LEN]; \ 467 | lookup_symbol_name((unsigned long)__builtin_return_address(0), _caller); \ 468 | if (_trace_enter_num < 100) { \ 469 | int rc = snprintf(_ret_msg, sizeof(_ret_msg), "%s < %s }", _caller, __func__); (void)rc;} \ 470 | tracef("%s > %s { @ %s:%d #%d" EOL, _caller, __func__, __file__, __LINE__, _trace_enter_num); \ 471 | } 472 | 473 | #define _trace_enter() \ 474 | static int _trace_enter_num; \ 475 | if (_hweight32(_trace_enter_num) < 2) { \ 476 | char _caller[_CTRACRE_BUF_LEN]; \ 477 | lookup_symbol_name((unsigned long)__builtin_return_address(0), _caller); \ 478 | tracef("%s:%d %s > %s #%d" EOL, __file__, __LINE__, _caller, __func__, _trace_enter_num); \ 479 | } \ 480 | _trace_enter_num++; \ 481 | 482 | /*__END_DECLS */ 483 | #endif /* CTRACER_H_INCLUDED */ 484 | #endif 485 | #endif /* __ASSEMBLY__ */ 486 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /lib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (C) 2013-2021 Constantine Shulyupin 4 | # 5 | # GPL License 6 | 7 | usage="\ 8 | lib.sh - Library of shell functions 9 | === 10 | Usage: 11 | 12 | Load commands to shell: 13 | . lib.sh 14 | 15 | Run a command with subshell: 16 | lib.sh 17 | " 18 | 19 | ############################################################################### 20 | # Common stuff 21 | 22 | MYSHELL=`/bin/ps -p $$ -o command=| sed "s:$0::;s:busybox ::"` 23 | export tab=$'\t' 24 | export NUMCPUS=`grep -c '^processor' /proc/cpuinfo` 25 | 26 | unset usage 27 | unset cmds 28 | declare -A usage 29 | declare -a cmds 30 | 31 | cmd() 32 | { 33 | cmds+=($1) 34 | usage[$1]="$2" 35 | } 36 | 37 | cmd lib-help "shows help for Lib.sh" 38 | lib-help() 39 | { 40 | echo -e "List of available commands:\n" 41 | 42 | for i in ${cmds[*]} 43 | do 44 | echo "$i - ${usage[$i]}" 45 | done 46 | } 47 | 48 | lib-snippets() 49 | { 50 | for i in "${!usage[@]}" 51 | do 52 | ( 53 | echo -e "$i - ${usage[$i]}\n====\n\n" 54 | echo -e "\`\`\` bash" 55 | if [ $(type -t $i) == alias ]; then 56 | a=$(type $i); echo alias ${a/ is aliased to \`/=\'} 57 | else 58 | #type "$i" | (read; cat) 59 | awk "/cmd $i/{f=1;next}; { if (f && /$^/)exit}; f" lib.sh 60 | fi 61 | echo "\`\`\`" 62 | ) > "snippets/$i.md" 63 | done 64 | } 65 | 66 | ############################################################################### 67 | # Short useful definitions and aliases 68 | 69 | GREP_OPTIONS="--devices=skip --color=auto " # avoid hanging grep on devices 70 | export GREP_COLORS='ms=01;38:mc=01;31:sl=02;38:cx=:fn=32:ln=32:bn=32:se=36' # print matched text in bold 71 | export HISTIGNORE="&:ls:[bf]g:exit" 72 | 73 | cmd ps-all "lists all processes" 74 | alias ps-all='ps -AF' 75 | 76 | cmd ps-threads "lists processes with threads" 77 | alias ps-threads="ps -ALf" 78 | 79 | cmd ps-recent "lists resent user processes" 80 | alias ps-recent='ps -x -o etime,pid,comm,%cpu,%mem --sort etime | head -n$((LINES-2))' 81 | 82 | cmd ps-tree "lists process tree via ps, see also pstree -p" 83 | alias ps-tree="ps -ejH" 84 | 85 | cmd ps-cpu "lists most CPU consuming processes" 86 | alias ps-cpu="ps -e -o pcpu,pid,comm --sort -%cpu | head -n 10" 87 | 88 | cmd ps-mem "lists most memory consuming processes" 89 | alias ps-mem="ps -e -o pmem,vsz,rss,pid,comm --sort -%mem | head -n 10" 90 | 91 | alias ps-cpu-mem="ps -e -o pcpu,pmem,rss,pid,comm --sort -%cpu,-%mem | head -n 10" 92 | 93 | cmd default-eth "provides default Ethernet interface" 94 | alias default-eth='ip route | awk "/default/ { print \$5 }"' 95 | 96 | cmd external-ip "Provides external IP" 97 | alias external-ip="dig +short myip.opendns.com @resolver1.opendns.com" 98 | 99 | cmd ps-wchan "shows what processes are waiting for, used in debugging blocked processes" 100 | alias ps-wchan="ps -e -o pid,comm,wchan" 101 | 102 | cmd ls-size "list files with sizes in bytes, shorter than ls -l" 103 | #alias ls-size='ls -s --block-size=1 -1' 104 | #alias ls-size='stat -c "%s$tab%n"' 105 | ls-size() { stat -c "%s$tab%n" `\ls "$@"`; } 106 | 107 | cmd mplayer-rotate-right "play video rotated right, used to play vertically captured videos" 108 | alias mplayer-rotate-right="mplayer -vf rotate=1" 109 | 110 | cmd hist "handy history, up to one screen length" 111 | alias hist='history $((LINES-2))' 112 | 113 | cmd deb-list "list content of specified deb file" 114 | alias deb-list="dpkg-deb --contents" 115 | 116 | cmd quotation-highlight "highlight text in quotation marks (\"quotation\")" 117 | ansi_rev=$'\e[7m' 118 | alias quotation-highlight=' sed " 119 | s|\\\\\\\\|:dbs:|g; 120 | s|\\\\\"|:bsq:|g; 121 | s|\\\\\"|:quotation:|g; 122 | s|\"\([^\"]*\?\)\"| $ansi_rev\1$reset_color |g; 123 | s|:quotation:|\\\\\"|g; 124 | s|:bsq:|\\\\\\\"|g; 125 | s|:dbs:|\\\\\\\\|g"' 126 | 127 | cmd keyboard-shortcuts "bash keyboard shortcuts. See also man readline." 128 | alias keyboard-shortcuts='(bind -P | grep -v "is not bound" | nl | 129 | sed " 130 | s| can be found on|:|; 131 | s|.$||; 132 | s|, \+| |g; 133 | s|\\\C-|^|g 134 | s|\\\e|+|g;" \ 135 | | pr --omit-header --expand-tabs --columns=2 -w $COLUMNS \ 136 | | expand; \ 137 | echo \"^\" = Ctrl, \"+\" = Escape) | quotation-highlight ' 138 | 139 | cmd tcpdump-text "tcpdump of payload in text" 140 | alias tcpdump-text="sudo tcpdump -l -s 0 -A '(((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and'" 141 | 142 | cmd make-debug "verbose make" 143 | alias make-debug="remake --debug=bv SHELL='/bin/bash -vx' " 144 | 145 | # git helpers 146 | 147 | cmd git-diff "handy git diff" 148 | alias git-diff='git diff --relative --no-prefix -w' 149 | 150 | alias repo-braches='repo forall -p -c git for-each-ref --format="%(refname:short)" refs/heads/*' 151 | cmd repo-braches "list git branches of repo subprojects" 152 | 153 | cmd git-prompt "sets shell prompt to show git branch" 154 | git-prompt() 155 | { 156 | PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' 157 | } 158 | 159 | cmd git-fixup "interactive fix up of specified number of last git commits" 160 | git-fixup() 161 | { 162 | git rebase -i HEAD~$1 . 163 | } 164 | 165 | cmd git-ign-add "add files' names with path to appropriate .gitignore list" 166 | git-ign-add() 167 | { 168 | for a in $*; do 169 | echo "$a" 170 | (cd `dirname "$a"`; \ls -d `basename "$a"` -1 >> .gitignore; git add .gitignore ) 171 | done 172 | } 173 | 174 | cmd log "safely prints messages to stderr" 175 | log() 176 | { 177 | # Note: echo "$@" > /dev/stderr - resets stderr 178 | ( 1>&2 echo "$@" ) 179 | } 180 | 181 | cmd trap-err "traps command failures, print return value and returns, better than set -o errexit" 182 | trap-err() 183 | { 184 | trap '(1>&2 echo -e $"\e[2;31mFAIL \e[0;39m ret=$? ${BASH_SOURCE[0]}:${LINENO} ${FUNCNAME[*]}";)' ERR 185 | } 186 | 187 | trap-err-return() 188 | { 189 | trap '(1>&2 echo -e $"\e[2;31mFAIL \e[0;39m ret=$? ${BASH_SOURCE[0]}:${LINENO} ${FUNCNAME[*]}"; return $ret; )' ERR 190 | } 191 | 192 | trap-err-test() 193 | { 194 | trap-err 195 | echo 1 196 | false 197 | echo 2 198 | trap '' ERR 199 | } 200 | 201 | ############################################################################### 202 | # Shell functions 203 | 204 | cmd system-status-short "shows short summary of system resources (RAM,CPU) usage" 205 | system-status-short() 206 | { 207 | inxi -M 208 | inxi 209 | grep -e MemTotal: -e MemAvailable: /proc/meminfo 210 | paste <(mpstat|grep %usr|sed "s/ \+/\n/g") <(mpstat|grep all|sed "s/ \+/\n/g") | \grep -e idle -e iowait -e sys 211 | ps-cpu 212 | ps-mem 213 | # blocked 214 | ps axo stat,pcpu,pid,comm | grep ^D 215 | } 216 | 217 | cmd system-status-long "shows long system status and statistics by running various system utilities" 218 | system-status-long() 219 | { 220 | grep "" /etc/issue /etc/*release 221 | sed 's/\([^ =]*\)=*\([^ ]*\)\s*/\1\t\2\n/g' /proc/cmdline | column -t|sort 222 | echo 223 | getconf LONG_BIT 224 | top -bn1 | head --lines 20 225 | echo 226 | free -m 227 | echo 228 | iostat -m 229 | echo 230 | mpstat # pkg sysstat 231 | echo 232 | vmstat -S M -s 233 | echo 234 | df --all --human-readable 235 | echo 236 | sudo -n parted -l || sudo -n flisk -l 237 | echo 238 | sudo -n dmidecode 239 | echo 240 | sudo -n lshw -short 241 | echo 242 | lsblk 243 | echo 244 | blkid 245 | echo 246 | lscpu 247 | echo 248 | ip addr 249 | echo 250 | ip route 251 | echo 252 | lsusb 253 | echo 254 | lspci 255 | echo -e "Biggest packages:" 256 | dpkg-query -W -f='${Installed-Size} ${Package} - ${Description}\n' | sort -n | tail -n 10 257 | echo -e "Old unused files:" 258 | find / -mount -type f -atime +1000 -ls 2> /dev/null 259 | grep -q -w "127.0.0.1.*$(hostname)" /etc/hosts || echo warning: no hostname for localhost 260 | } 261 | 262 | cmd shell-type "tries to identify type of current shell" 263 | shell-type() 264 | { 265 | # adopted from http://stackoverflow.com/questions/5166657/how-do-i-tell-what-type-my-shell-is 266 | # see also http://www.in-ulm.de/~mascheck/various/whatshell/whatshell.sh.html 267 | # also can be useful: 268 | # ps -p $$ -o comm= 269 | # ps -p $$ -o command= 270 | if test -n "$ZSH_VERSION"; then 271 | echo zsh 272 | elif test -n "$BASH_VERSION"; then 273 | echo bash 274 | elif test -n "$KSH_VERSION"; then 275 | echo ksh 276 | else 277 | /bin/ps -p $$ -o command=| sed "s@$0@@;s@busybox @@" 278 | fi 279 | } 280 | 281 | cmd ps-of "specified process info" 282 | ps-of() 283 | { 284 | # ps u -C "$1" 285 | ps u `pidof "$@"` 286 | } 287 | 288 | cmd proc-mem-usage "returns percentage memory usage by specified process" 289 | proc-mem-usage() 290 | { 291 | ps h -o pmem -C "$1" 292 | } 293 | 294 | cmd dir-diff "compare listings of two specified directories" 295 | dir-diff() 296 | { 297 | find "$1" -type f -printf "%P\n" | sort > "$1/list.tmp" 298 | find "$2" -type f -printf "%P\n" | sort > "$2/list.tmp" 299 | kdiff3 "$1/list.tmp" "$2/list.tmp" 300 | } 301 | 302 | cmd retry "retry argument operation till success" 303 | retry() 304 | { 305 | # see also "watch" 306 | while ( ! "$@" ) do 307 | log retry 308 | sleep 1 309 | done 310 | } 311 | 312 | exclude_dirs=("*.log" \*.gcov \*.gcda 313 | "*_icgraph.*" "*_cgraph.*" "inherit_graph_*.*" "*_incl.*" html 314 | tmp .git .repo .svn "*._comment" .dropbox.cache third-party out 315 | intermediates .gradle .idea "_build_*" .cxx Debug CMakeFiles build) 316 | 317 | if [ "$BASH_VERSION" ]; then 318 | exclude_dirs_with_coma="$(IFS=','$IFS; eval echo "${exclude_dirs[*]}")" 319 | grep_exclude_dirs="$(eval echo "'--exclude-dir='"{$exclude_dirs_with_coma} )" 320 | find_exclude_body="$(eval echo "' -o -name '"{$exclude_dirs_with_coma})" 321 | find_exclude="( ( -false $find_exclude_body ) -a -prune ) -o " 322 | else 323 | exclude_dirs_with_coma= 324 | grep_exclude_dirs= 325 | find_exclude_body= 326 | find_exclude= 327 | fi 328 | 329 | exclude_dir_add() 330 | { 331 | while [ -n "$1" ]; do 332 | exclude_dirs_with_coma+=",$1" 333 | grep_exclude_dirs+=" --exclude-dir=$1" 334 | find_exclude_body+=" -o -name $1" 335 | shift 336 | done 337 | find_exclude="( ( -false $find_exclude_body ) -a -prune ) -o " 338 | } 339 | 340 | cmd duplicates 'finds duplicate files. To follow symbolic links run duplicate -L $DIR' 341 | duplicates() 342 | { 343 | # Features: 344 | # * Fast - because it checks sizes first 345 | # and filters same linked files by checking inode (%i) 346 | # * Sorts files by size to help you to delete biggest files first 347 | # 348 | # Troubleshooting: 349 | # on out of memory define TMPDIR 350 | # 351 | set -o noglob 352 | find "$@" $find_exclude -type f \ 353 | -printf "%10i\t%10s\t%p\n" \ 354 | | sort -n \ 355 | | uniq --unique -w10 \ 356 | | cut -f 2,3 | sort -n \ 357 | | uniq --all-repeated -w 10 \ 358 | | cut -f 2 \ 359 | | perl -pe "s/\n/\0/g" \ 360 | | xargs -0 -i{} sha1sum "{}" | sort \ 361 | | uniq --all-repeated=separate -w32 \ 362 | | cut -d ' ' -f 3- 363 | set +o noglob 364 | } 365 | 366 | cmd for-each "applies an operation to set of arguments one by one" 367 | for-each() 368 | { 369 | op=$1 370 | shift 371 | for arg in "$@"; do 372 | eval "$op" \"$arg\" 373 | done 374 | } 375 | 376 | cmd str "readable string manipulations: ltrim, ltrim-max, rtrim, rtrim-max, subst, subst-all" 377 | str() 378 | { 379 | case $1 in 380 | (ltrim) echo "${2#$3}" ;; 381 | (ltrim-max) echo "${2##$3}";; 382 | (rtrim) echo "${2%$3}";; 383 | (rtrim-max) echo "${2%%$3}";; 384 | (subst) echo "${2/$3/$4}";; 385 | (subst-all) echo "${2//$3/$4}";; 386 | (ext) echo "${2#*.}";; 387 | (rtrim-ext) echo "${2%%.*}";; # path without extension 388 | (base) # just filename without path and extension 389 | expr \ 390 | match "$2" '.*/\(.*\)\.tar' \| \ 391 | match "$2" '.*/\(.*\)\.' \| \ 392 | match "$2" '.*/\(.*\)' 393 | ;; 394 | esac 395 | # More: https://www.tldp.org/LDP/abs/html/string-manipulation.html 396 | } 397 | 398 | cmd postfix-extract "return filename postfix: path/name[-_]postfix.ext -> postfix" 399 | postfix-extract() 400 | { 401 | a=${1%.*} 402 | echo "${a##*[-_]}" 403 | } 404 | 405 | cmd unzip-dir "handy unzip to directory with name of zip-file" 406 | unzip-dir() 407 | { 408 | unzip "$@" -d `str base "$1"` 409 | } 410 | 411 | cmd mac-to-ip "looks for LAN IP for MAC" 412 | mac-to-ip() 413 | { 414 | ( 415 | (for b in $(ip addr ls | awk '/inet .* brd/ {print $4}'); do 416 | ping -q -c 1 -b $b &> /dev/null 417 | done ) & 418 | ) 2> /dev/null 419 | while ! a=$(arp -n | grep -i "$1"); do sleep 1; log 'waitig' ; done; 420 | echo "$a" | (read a1 a2; echo $a1) 421 | } 422 | 423 | cmd ip-to-mac "show MAC address for specified IP in LAN" 424 | ip-to-mac() 425 | { 426 | if which arping > /dev/null; then 427 | arping -c 1 "$1" 2> /dev/null | perl -ne '/.*\[(.*)\].*/ && print "$1\n"' 428 | else 429 | ping -c 1 -w 1 "$1" &> /dev/null 430 | arp -na | grep "$1" | cut -f 4 -d ' ' 431 | fi 432 | } 433 | 434 | cmd fs-usage "show biggest directories and optionally files on a filesystem, for example on root: fs-usage -a /" 435 | fs-usage() 436 | { 437 | du --time --one-file-system "$@" | sort -n | tail -n $((LINES-2)) | while read s n; do echo $(numfmt --to=iec-i $((1024*s))) $n; done 438 | df "$@" 439 | } 440 | 441 | cmd PATH-append "appends argument to PATH, if required" 442 | PATH-append() 443 | { 444 | if [[ ":$PATH:" == *":$1:"* ]] 445 | then 446 | echo "$1 is already in path" 447 | else 448 | export PATH="$PATH:$1" 449 | fi 450 | } 451 | 452 | cmd PATH-insert "inserts argument to head of PATH, if required" 453 | PATH-insert() 454 | { 455 | if [[ ":$PATH:" == *":$1:"* ]] 456 | then 457 | echo "$1 is already in path" 458 | else 459 | export PATH="$1:$PATH" 460 | fi 461 | } 462 | 463 | cmd PATH-remove "removes argument from PATH" 464 | PATH-remove() 465 | { 466 | PATH=$(echo ":$PATH:"| sed "s|:$1:|:|g" | sed "s|::||g;s|^:||;s|:$||") 467 | } 468 | 469 | cmd PATH-append "prints PATH in readable format" 470 | PATH-show() 471 | { 472 | echo $PATH | sed "s/:/\n/g" 473 | } 474 | 475 | cmd gcc-set "append a string to a file if it not yet present there" 476 | file-append-once() 477 | { 478 | mkdir -p $(dirname "$1") 479 | grep --quiet --line-regexp --fixed-strings "$2" "$1" && return 480 | test -w "$1" && echo "$2" >> "$1" || echo "$2" | sudo tee -a "$1" 481 | } 482 | 483 | cmd gcc-set "set specified [cross] compiler as default in environment" 484 | gcc-set() 485 | { 486 | #export PATH=/usr/sbin:/usr/bin:/sbin:/bin: 487 | PATH-append $(dirname $(which "$1")) 488 | export CROSS_COMPILE=$(expr match "$(basename $1)" '\(.*-\)') 489 | export CC=${CROSS_COMPILE}gcc 490 | export AR=${CROSS_COMPILE}ar 491 | export LD=${CROSS_COMPILE}ld 492 | export AS=${CROSS_COMPILE}as 493 | export CPP=${CROSS_COMPILE}cpp 494 | export CXX=${CROSS_COMPILE}c++ 495 | echo Using: 496 | which "$CC" 497 | mach=`$CC -dumpmachine` 498 | export ARCH=${mach%%-*} 499 | PS1='$ARCH \w \$ ' 500 | $CC -v 2>&1 | grep 'gcc version' 501 | } 502 | 503 | cmd replace "replaces substring arg1 to substring arg2 in directory arg3" 504 | replace() 505 | { 506 | test "$1" || { echo ${usage[replace]}; return; } 507 | grep "$1" "$3" \ 508 | -rl --exclude .orig --exclude .git --binary-files=without-match --exclude-dir=.svn --exclude-dir=.git -P \ 509 | | xargs sed -i "s|$1|$2|g" 510 | } 511 | 512 | https-to-git() 513 | { 514 | a=$(expr match "$1" "^https://github.com/\(.*\)") && { echo git@github.com:$a; return;} 515 | echo "$1" 516 | } 517 | 518 | cmd get-source "download and unpack an open source tarball" 519 | get-source() 520 | { 521 | local a=$(https-to-git "$1") 522 | case $a in 523 | (git* | *.git | https://github.com/*) git clone $a ;; 524 | (svn*) git checkout $a ;; 525 | (*) 526 | fn=$(basename $a) 527 | n=${fn%%.tar.*} 528 | ! test -f ~/Downloads/"$fn" && (expr match "$a" "^http" || expr match "$a" "^ftp" ) > /dev/null && wget -P ~/Downloads/ "$a" 529 | [ -e "$n" ] || aunpack -q ~/Downloads/"$fn" 530 | esac 531 | } 532 | 533 | cmd gnu-build "universal complete build and install of gnu package" 534 | gnu-build() 535 | { 536 | [ "$CC" ] || CC=gcc 537 | [ "$1" ] && get-source $1 || n=. 538 | shift 539 | pushd $n 540 | if [ -d debian ]; then 541 | # apt-get build-dep 542 | dpkg-buildpackage -rfakeroot -uc -b 543 | fi 544 | test -f CMakeLists.txt && cmake -B build && make -C build 545 | test configure.ac -nt configure && ./autogen.sh -q 546 | test -e configure || autoreconf --install # configure.ac configure.in 547 | if [ -e configure ]; then 548 | configure_opt="$configure_opt_init -q" 549 | if [ -n "$DESTDIR" ]; then 550 | configure_opt+=" --prefix=/ --includedir=/include " 551 | fi 552 | configure_opt+=" CPPFLAGS='${CPPFLAGS}'" 553 | configure_opt+=" LDFLAGS='${LDFLAGS}'" 554 | if [ -n "${CROSS_COMPILE}" ]; then 555 | configure_opt+=" --host=${CROSS_COMPILE%-}" 556 | fi 557 | test "${staging}" && configure_opt+=" --with-sysroot=${staging}" 558 | configure_opt+=" $* " 559 | mkdir -p $($CC -dumpmachine)-build 560 | pushd $_ 561 | test -e Makefile || ( echo "Configuring $configure_opt" && eval ../configure $configure_opt ) 562 | make -j$NUMCPUS --load-average=$NUMCPUS -ws 563 | # && make -k install || sudo -H make -k install 564 | ret=$? 565 | popd 566 | fi 567 | ls 568 | if [ -e Makefile.PL ]; then 569 | perl Makefile.PL 570 | make 571 | sudo make -k install 572 | ret=$? 573 | fi 574 | popd 575 | return $ret 576 | } 577 | 578 | cmd alternative-config-build "build of package, alternatively to gnu-build" 579 | alternative-config-build() 580 | { 581 | [ "$CC" ] || CC=gcc 582 | get-source $1 583 | shift 584 | mkdir -p $n/$($CC -dumpmachine)-build~ # '~' to skip by lndir 585 | pushd $_ 586 | lndir -silent .. 587 | ./configure -q "$@" 588 | make -j$NUMCPUS --load-average=$NUMCPUS -ws && 589 | make install 590 | ret=$? 591 | popd 592 | return $ret 593 | } 594 | 595 | cmd build-env "configure staging build environment" 596 | build-env() 597 | { 598 | staging=$(readlink --canonicalize $1) 599 | PKG_CONFIG_DIR= #https://autotools.io/pkgconfig/cross-compiling.html 600 | PKG_CONFIG_SYSROOT_DIR=$staging 601 | #export PKG_CONFIG_PATH=$staging/lib/pkgconfig 602 | PKG_CONFIG_LIBDIR=$PKG_CONFIG_SYSROOT_DIR/lib/pkgconfig 603 | DESTDIR=$staging # used by make install 604 | CPPFLAGS=-I${staging}/include 605 | LDFLAGS=-L${staging}/lib 606 | LDFLAGS+=' '-Wl,-rpath-link=${staging}/lib 607 | export staging PKG_CONFIG_DIR PKG_CONFIG_SYSROOT_DIR DESTDIR CPPFLAGS LDFLAGS 608 | } 609 | 610 | cmd glib-arm-build "demonstration of arm compilation of glib from the scratch" 611 | glib-arm-build() 612 | { 613 | gcc-set /usr/bin/arm-linux-gnueabi-gcc 614 | build-env staging-$($CC -dumpmachine) 615 | alternative-config-build http://zlib.net/zlib-1.2.8.tar.gz --prefix=/ 616 | gnu-build ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz 617 | cp -a ${staging}/lib/libffi-*/include ${staging}/ 618 | export glib_cv_stack_grows=no glib_cv_uscore=no ac_cv_func_posix_getpwuid_r=yes ac_cv_func_posix_getgrgid_r=yes 619 | gnu-build http://ftp.gnome.org/pub/gnome/sources/glib/2.48/glib-2.48.1.tar.xz --with-pcre=internal 620 | file -L staging-$($CC -dumpmachine)/lib/libglib-2.0.so 621 | return $? 622 | } 623 | 624 | cmd staging-dir-fix "fix parameter libdir in *.la files in staging cross-compilation directory" 625 | staging-dir-fix() 626 | { 627 | sed -i "s|^libdir='//\?lib'|libdir='`readlink --canonicalize "$1"`/lib'|" \ 628 | `grep --no-messages --recursive --files-with-matches --include *.la "libdir='//\?lib" "$1"` 629 | grep -r --include *.la "libdir=" "$1" 630 | } 631 | 632 | cmd mem-drop-caches "drop caches and free this memory. Practically not required" 633 | alias mem-drop-caches="sync; echo 3 | sudo tee /proc/sys/vm/drop-caches" 634 | 635 | cmd gdb-print-prepare "utility to print C,C++ variables and structs at runtime" 636 | gdb-print-prepare() 637 | { 638 | if [[ $# == 0 ]]; then 639 | cat <<-EOF 640 | 641 | Usage: 642 | 643 | Mark print points in C or C++ sources with pseudo comment: 644 | // gdb_print(big_struct) 645 | gdb-print-prepare \$src > app.gdb 646 | gdb --batch --quiet --command=app.gdb \$app 647 | 648 | See file gdb-print-demo.c for example. 649 | 650 | EOF 651 | return 652 | fi 653 | cat <<-EOF 654 | set auto-load safe-path / 655 | EOF 656 | grep --with-filename --line-number --recursive --only-matching 'gdb_print(.*)' $1 | \ 657 | while IFS=$'\t :;()' read file line func var rest; do 658 | cat <<-EOF 659 | break $file:$line 660 | commands 661 | silent 662 | where 1 663 | echo \\n$var\\n 664 | print $var 665 | cont 666 | end 667 | EOF 668 | done 669 | cat <<-EOF 670 | run 671 | echo ---\\n 672 | EOF 673 | } 674 | 675 | cmd wget-as-me "Run wget with cookies from firefox to access authenticated data" 676 | wget-as-me() 677 | { 678 | sqlite3 -separator "$tab" $(ls -1t $HOME/.mozilla/firefox/*.default*/cookies.sqlite | head -1) \ 679 | 'select host, "TRUE", path, "FALSE", expiry, name, value from moz_cookies' \ 680 | > ~/.mozilla/cookies.txt 681 | wget -q --load-cookies ~/.mozilla/cookies.txt "$@" 682 | ret=$? 683 | #( 1>&2 echo echo ret=$ret ) 684 | return $ret 685 | } 686 | 687 | cmd calc "calculate with bc specified floating point expression" 688 | calc() 689 | { 690 | # see also http://www.isthe.com/chongo/tech/comp/calc/ 691 | echo "scale=4;" "$@" | bc 692 | } 693 | 694 | cmd md5sum-make "create md5 files for each specified file separately" 695 | md5sum-make() 696 | { 697 | while [ -n "$1" ]; do 698 | md5sum "$1" > "$1.md5" 699 | echo "$1.md5" 700 | shift 701 | done 702 | } 703 | 704 | red_color=$'\033[31m' 705 | green_color=$'\033[32m' 706 | reset_color=$'\033[m' 707 | cmd check "runs verbosely specified command and prints return status" 708 | check() 709 | { 710 | echo -n "Running: $@ : " 711 | eval "$@" && { let successes+=1; echo -e "$? ${green_color}OK$reset_color"; } || { let fails+=1; echo -e "$? ${red_color}Fail $reset_color"; } 712 | } 713 | 714 | google-chrome-install() 715 | { 716 | wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 717 | sudo dpkg -i google-chrome-stable_current_amd64.deb 718 | } 719 | 720 | # used in lib-sh-demo only 721 | v() 722 | { 723 | echo ">" "$@" 724 | eval "$@" 725 | } 726 | 727 | # used in lib-sh-demo only 728 | eq() 729 | { 730 | a="$1" 731 | echo -n "$a " 732 | shift 733 | if [ "$a" == $(eval "$@") ]; then echo -n '= '; else echo -n '!= '; fi 734 | echo "$@" 735 | } 736 | 737 | cmd lib-sh-demo "run lib.sh functions for demonstration and testing" 738 | lib-sh-demo() 739 | { 740 | eq '4.tar.gz' str ext '1/2/3.4.tar.gz' 741 | eq '3' str base '1/2/3.4.tar.gz' 742 | v postfix-extract path/name-postfix.ext 743 | v for-each echo aaa bbb ccc 744 | mkdir -p dup/sub 745 | echo 1 > dup/1 746 | cp dup/1 dup/1.1 747 | cp dup/1 dup/sub/ 748 | echo 2 > dup/2 749 | 750 | v duplicates dup 751 | check true 752 | check false 753 | #not supported 754 | #v 'wget-as-me "http://mail.google.com/mail?nocheckbrowser&ui=html" -O- \ 755 | # | lynx -stdin -dump -width=$COLUMNS | grep ^Inbox -A 10' 756 | } 757 | 758 | cmd doxygen-bootstrap "generic handy doxygen wrapper" 759 | doxygen-bootstrap() 760 | { 761 | if [ ! -e Doxyfile ]; then 762 | cat > Doxyfile <<-EOF 763 | PROJECT_NAME = "$(basename $PWD)" 764 | EXTRACT_ALL = YES 765 | EXTRACT_STATIC = YES 766 | RECURSIVE = YES 767 | EXCLUDE = html 768 | GENERATE_TREEVIEW = YES 769 | GENERATE_LATEX = NO 770 | HAVE_DOT = YES 771 | DOT_FONTSIZE = 15 772 | CALL_GRAPH = YES 773 | CALLER_GRAPH = YES 774 | #INTERACTIVE_SVG = YES 775 | DOT_IMAGE_FORMAT = svg 776 | #DOT_TRANSPARENT = YES 777 | DOT_MULTI_TARGETS = NO 778 | DOT_CLEANUP = NO 779 | OPTIMIZE_OUTPUT_FOR_C = YES 780 | DOT_FONTNAME = Ubuntu 781 | #CASE_SENSE_NAMES = YES 782 | SOURCE_BROWSER = YES 783 | QUIET = yes 784 | REFERENCED_BY_RELATION = yes 785 | REFERENCES_RELATION = yes 786 | EOF 787 | # command doxygen -u 788 | fi 789 | cat Doxyfile | doxygen -u - > Doxyfile.explained 790 | cat Doxyfile | doxygen -s -u - > Doxyfile.expanded 791 | command doxygen "$@" 2> doxygen.log 792 | xdg-open html/index.html || firefox html/index.html 793 | } 794 | 795 | cmd load-watch "kills memory and cpu hogs when load average is too high" 796 | csi=$'\e[' 797 | load-watch() 798 | { 799 | local nproc=$(getconf _NPROCESSORS_ONLN) 800 | echo 801 | while true; do 802 | echo -n ${csi}A 803 | echo -n $(date "+%T $SECONDS ") " " 804 | local load 805 | free=$( grep MemAvailable: /proc/meminfo | (read a b c d e; echo $((b/1024))) ) 806 | IFS="/ " read -a load < /proc/loadavg 807 | local loadproc=$((10#${load/./}00/${nproc}00)) # '10#' is to force decimal, because 'load' starts from 0 808 | local pcpu=$(echo $(ps --no-headers -e -o pid,comm,pcpu --sort -%cpu | head -n 1)) 809 | local pmem=$(echo $(ps --no-headers -e -o pid,comm,pmem --sort -%mem | head -n 1)) 810 | echo -n "load=$load $loadproc% running=${load[3]} free=$free MB, $pcpu% cpu, $pmem% mem" 811 | echo "${csi}K" 812 | test -w /proc/${pcpu%% *}/oom_score_adj && echo 1000 > /proc/${pcpu%% *}/oom_score_adj 813 | test -w /proc/${pmem%% *}/oom_score_adj && echo 1000 > /proc/${pmem%% *}/oom_score_adj 814 | if [ \( ${load[3]} -gt $((1 * ${nproc})) \) -a \( $loadproc -gt 200 \) ]; then 815 | echo killing "${pcpu} " 816 | echo 817 | kill "${pcpu%% *}" 818 | fi 819 | if [ $free -lt 200 ]; then 820 | echo killing "${pmem} " 821 | echo 822 | kill "${pmem%% *}" 823 | fi 824 | SECONDS=0 825 | read -t 5 826 | done 827 | } 828 | 829 | load-monitor() 830 | { 831 | local nproc=$(getconf _NPROCESSORS_ONLN) 832 | echo 833 | while sleep 1; do 834 | local load 835 | IFS="/ " read -a load < /proc/loadavg 836 | echo "${csi}K" 837 | if [ ${load[3]} -gt $((${nproc})) ]; then 838 | date "+%y-%m-%d %T" 839 | free=$( grep MemAvailable: /proc/meminfo | (read a b c d e; echo $((b/1024))) ) 840 | local loadproc=$((10#${load/./}00/${nproc}00)) # '10#' is to force decimal, because 'load' starts from 0 841 | echo -n "load=$loadproc% running=${load[3]} free=$free MB" 842 | ps -e -o pcpu,pmem,pid,comm,args:5 --sort -%cpu,-%mem | cut -c -100 | head -n 10 843 | echo 844 | fi 845 | done 846 | } 847 | 848 | cmd dts-tags "extacts tags (ctags format) from device tree source files" 849 | dts-tags() 850 | { 851 | grep -oH '\w\+:' "$@" | awk -F: '{print $2"\t"$1"\t/"$2":"}' | LC_ALL=C sort 852 | } 853 | 854 | security-checks() 855 | { 856 | echo GOOD: 857 | egrep -i '^PubKeyAuthentication yes|^PasswordAuthentication no' <(sshd -T 2> /dev/null) /etc/ssh/sshd_config 858 | echo BAD: 859 | egrep -i '^PasswordAuthentication yes|^PermitRootLogin yes|^PermitEmptyPasswords yes' <(sshd -T 2> /dev/null) /etc/ssh/sshd_config 860 | echo -- done 861 | echo Lynis: 862 | sudo lynis audit system 863 | echo Chkrootkit: 864 | sudo chkrootkit -q 865 | } 866 | 867 | if [ -n "$*" ]; then 868 | eval "$*" # execute arguments 869 | echo $* finished, ret=$? 870 | else 871 | if [ "$0" != "$BASH_SOURCE" ]; then 872 | echo Lib.sh functions are loaded into the shell environment 873 | else 874 | echo Lib.sh - a library of shell utility functions 875 | echo To get help run \"$BASH_SOURCE lib-help\" 876 | fi 877 | fi 878 | --------------------------------------------------------------------------------