helpers 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. #!/usr/bin/env bash
  2. # shellcheck shell=bash
  3. ################################################################################
  4. ####################### Definitions of global functions ########################
  5. ################################################################################
  6. # ``````````````````````````````````````````````````````````````````````````````
  7. # Function name: _exit_()
  8. #
  9. # Description:
  10. # Covers the default exit command.
  11. #
  12. # Usage:
  13. # _exit_ value
  14. #
  15. # Examples:
  16. # _exit_ 0
  17. #
  18. function _exit_() {
  19. local _FUNCTION_ID="_exit_"
  20. local _STATE="0"
  21. _STATUS="$1"
  22. # Remember that for it a trap is executed that intercepts
  23. # the exit command (at the end of this function).
  24. if [[ "$_STATUS" -eq 0 ]] ; then
  25. # Add tasks when exiting the code is equal 0.
  26. true
  27. else
  28. # Add tasks when exiting the code is non equal 0.
  29. false
  30. fi
  31. exit "$_STATUS"
  32. }
  33. # ``````````````````````````````````````````````````````````````````````````````
  34. # Function name: _get_trap_SIG()
  35. #
  36. # Description:
  37. # Ensuring they always perform necessary cleanup operations,
  38. # even when something unexpected goes wrong. It can handle
  39. # all output signals.
  40. #
  41. # Usage:
  42. # trap _get_trap_SIG SIGNAL
  43. #
  44. # Examples:
  45. # trap _get_trap_SIG EXIT
  46. # trap "_get_trap_SIG SIGS" SIGHUP SIGTERM
  47. #
  48. function _get_trap_SIG() {
  49. local _FUNCTION_ID="_get_trap_SIG"
  50. local _STATE="${_STATUS:-}"
  51. local _SIG_type="$1"
  52. # Remember not to duplicate tasks in the _exit_() and _get_trap_SIG()
  53. # functions. Tasks for the _exit_() function only work within it
  54. # and refer to the exit mechanism. Tasks in the _get_trap_SIG() function
  55. # can refer to specific signal or all signals.
  56. if [ -z "$_STATE" ] ; then _STATE=254
  57. # Performs specific actions for the EXIT signal.
  58. elif [[ "$_SIG_type" == "EXIT" ]] ; then
  59. # Unset variables (e.g. global):
  60. # - local _to_unset=("$IFS_ORIG" "$IFS_HACK" "$IFS" "$PATH")
  61. local _to_unset=("$PATH")
  62. # Running tasks before the end of the script.
  63. _after_init
  64. # shellcheck disable=SC2034
  65. for i in "${_to_unset[@]}" ; do unset i ; done
  66. # You can cover the code supplied from the _exit_() function
  67. # (in this case) or set a new one.
  68. _STATE="${_STATUS:-}"
  69. # Performs specific actions fot the other signals.
  70. # In this example, using the SIGS string, we mark several output signals
  71. # (see the second example in the description of the function).
  72. elif [[ "$_SIG_type" == "SIGS" ]] ; then
  73. # You can cover the code supplied from the function
  74. # or set a new one.
  75. _STATE="${_STATUS:-}"
  76. else
  77. # In this block the kill command was originally used,
  78. # however, it suspended the operation of dracnmap.
  79. # The lack of this command terminates the process
  80. # and does not cause the above problems.
  81. _STATE="255"
  82. fi
  83. _logger "exit" \
  84. "$_FUNCTION_ID > ${_SIG_type} (${_STATE})"
  85. return "$_STATE"
  86. }
  87. # ``````````````````````````````````````````````````````````````````````````````
  88. # Function name: _logger()
  89. #
  90. # Description:
  91. # Saving selected operation states to a log file
  92. # and allows you to terminate the script with 'stop' signal.
  93. #
  94. # Four states of message type:
  95. # info - normal information
  96. # head - normal information (header)
  97. # warn - warning information
  98. # stop - interrupts script execution
  99. #
  100. # Usage:
  101. # _logger "type" "message"
  102. #
  103. # Examples:
  104. # _logger "info" "load config file properly"
  105. # _logger "stop" "not connected"
  106. #
  107. function _logger() {
  108. local _FUNCTION_ID="_logger"
  109. local _STATE="0"
  110. local _type="$1"
  111. local _to_log=""
  112. local _conv_type=""
  113. _to_log=$(shift ; echo "$@")
  114. _conv_type=$(echo "$_type" | tr '[:lower:]' '[:upper:]')
  115. # shellcheck disable=SC2154
  116. if [[ ! -d "$_log_directory" && ! -L "$_log_directory" ]] ; then
  117. mkdir -p "$_log_directory" ; fi
  118. # Normal debug mode (output the same as the contents of the log file).
  119. # shellcheck disable=SC2154
  120. if [[ "$stdout_mode" == "debug" ]] ; then
  121. printf "%s %s: [%s] %s\\n" \
  122. "$(date +"%d/%m/%y %X")" \
  123. "$_init_name" \
  124. "$_conv_type" \
  125. "$_to_log" \
  126. | tee -a "$_log_path"
  127. # The decision whether an INFO is to be only log to a file
  128. # or to a file and to standard output.
  129. else
  130. printf "%s %s: [%s] %s\\n" \
  131. "$(date +"%d/%m/%y %X")" \
  132. "$_init_name" \
  133. "$_conv_type" \
  134. "$_to_log" \
  135. >>"$_log_path"
  136. fi
  137. # By means of this construction, we can terminate the operation
  138. # of the script with the action of logging into the log file.
  139. # This do not have to remember to place the _exit_ <value> function
  140. # in 'exit' script points. If you prefer to have more control,
  141. # do not use the _logger function with the 'stop' parameter.
  142. if [[ "$_type" == "stop" ]] ; then _exit_ 255 ; fi
  143. return "$_STATE"
  144. }
  145. # ``````````````````````````````````````````````````````````````````````````````
  146. # Function name: _sprintf()
  147. #
  148. # Description:
  149. # Function designed to output to the screen in a clear format.
  150. #
  151. # Usage:
  152. # _sprintf "type" "message"
  153. #
  154. # Examples:
  155. # _sprintf "head" "correct certificate: $_ssl_cert_file"
  156. #
  157. function _sprintf() {
  158. local _FUNCTION_ID="_sprintf"
  159. local _STATE="0"
  160. local _s_type="$1"
  161. local _s_info="$2"
  162. # Determine the type of character and color for each type
  163. # of output information.
  164. if [[ "$_s_type" == "head" ]] ; then
  165. s_char="+"
  166. s_trgb="1;32"
  167. elif [[ "$_s_type" == "info" ]] ; then
  168. s_char="-"
  169. s_trgb="0;33"
  170. elif [[ "$_s_type" == "warn" ]] ; then
  171. s_char="!"
  172. s_trgb="1;37"
  173. elif [[ "$_s_type" == "stop" ]] ; then
  174. s_char="!"
  175. s_trgb="1;31"
  176. else
  177. s_char="-"
  178. s_trgb="0;37"
  179. fi
  180. # If you run the tool in verbose mode do not display output using _sprintf.
  181. if [[ "$stdout_mode" != "debug" ]] ; then
  182. if [[ "$_s_type" == "spin" ]] && [[ ! -z "$_s_info" ]] ; then
  183. # Process id of the previous running command.
  184. local _pid="$_s_info"
  185. local _sc='-\|/'
  186. # Verify that the process is still running.
  187. local _n="0"
  188. # shellcheck disable=SC2143
  189. while [[ $(ps a | awk '{print $1}' | grep -w "$_pid") ]] ; do
  190. _n=$(( ( _n + 1 ) % 4 ))
  191. printf "\\r[%s]" "${_sc:_n:1}"
  192. sleep 0.1
  193. done
  194. # If the end, we clean.
  195. printf "\\r"
  196. else
  197. # Normal execution if:
  198. # - spinner has not been called
  199. # - spinner completed
  200. # If verbose mode is enabled, display info message.
  201. # shellcheck disable=SC2154
  202. if [[ "$printf_mode" == "verbose" ]] && [[ "$_s_type" == "info" ]] ; then
  203. printf '[\e['${s_trgb}'m%s\e[m] %s\n' "$s_char" "$_s_info"
  204. else
  205. # If not, just display only the head, warn or stop string.
  206. # shellcheck disable=SC2154
  207. if [[ "$_s_type" == "head" ]] ; then
  208. if [[ "$s_color" == "true" ]] ; then
  209. c_trgb="1;39"
  210. printf '[\e['${s_trgb}'m%s\e[m] \e['${c_trgb}'m%s\e[m\n' "$s_char" "$_s_info"
  211. else
  212. printf '[\e['${s_trgb}'m%s\e[m] %s\n' "$s_char" "$_s_info"
  213. fi
  214. elif [[ "$_s_type" == "warn" ]] ; then
  215. if [[ "$s_color" == "true" ]] ; then
  216. c_trgb="1;43"
  217. printf '[\e['${s_trgb}'m%s\e[m] \e['${c_trgb}'m%s\e[m\n' "$s_char" "$_s_info"
  218. else
  219. printf '[\e['${s_trgb}'m%s\e[m] %s\n' "$s_char" "$_s_info"
  220. fi
  221. elif [[ "$_s_type" == "stop" ]] ; then
  222. if [[ "$s_color" == "true" ]] ; then
  223. c_trgb="1;41"
  224. printf '[\e['${s_trgb}'m%s\e[m] \e['${c_trgb}'m%s\e[m\n' "$s_char" "$_s_info"
  225. else
  226. printf '[\e['${s_trgb}'m%s\e[m] %s\n' "$s_char" "$_s_info"
  227. fi
  228. fi
  229. fi
  230. fi
  231. fi
  232. return "$_STATE"
  233. }
  234. # ``````````````````````````````````````````````````````````````````````````````
  235. # Function name: _init_cmd()
  236. #
  237. # Description:
  238. # Function executing given as a command parameter.
  239. #
  240. # Usage:
  241. # _init_cmd "parameter"
  242. #
  243. # Examples:
  244. # _init_cmd "eval cd /etc/init.d && ls"
  245. #
  246. function _init_cmd() {
  247. local _FUNCTION_ID="_init_cmd"
  248. local _STATE="0"
  249. local _cmd="$1"
  250. # Uncomment if you want to display executed commands.
  251. # _sprintf "info" "init: \"$_cmd\""
  252. _logger "info" \
  253. "${_FUNCTION_ID}()" \
  254. "init: $_cmd"
  255. # Execute command and exit save to file.
  256. # shellcheck disable=SC2154
  257. $_cmd >>"$_log_stdout" 2>&1 &
  258. # We keep pid of the last command.
  259. _pid="$!"
  260. # When the '(command) &' command is performed.
  261. _sprintf "spin" "$_pid"
  262. # Very important line:
  263. # We define the state of the output job from the background.
  264. wait "$_pid" &>/dev/null && _state="0" || _state="1"
  265. if [[ "$_state" -eq 0 ]] ; then
  266. _logger "info" \
  267. "${_FUNCTION_ID}()" \
  268. "result: pass"
  269. else
  270. _sprintf "stop" "result: fail"
  271. _logger "stop" \
  272. "${_FUNCTION_ID}()" \
  273. "result: fail"
  274. fi
  275. _STATE="$_state"
  276. return "$_STATE"
  277. }
  278. # ``````````````````````````````````````````````````````````````````````````````
  279. # Function name: _init_function()
  280. #
  281. # Description:
  282. # It deals with launching functions:
  283. # - creates a simple environment for the functions you perform
  284. # - operates on message to display and command to execute
  285. #
  286. # Usage:
  287. # _init_function function_name params
  288. #
  289. # Examples:
  290. # _init_function "CheckConn 172.20.20.50 22"
  291. #
  292. function _init_function() {
  293. local _FUNCTION_ID="_init_function"
  294. local _STATE="0"
  295. local _args=("$@")
  296. local _cmd_begtime="0"
  297. local _cmd_endtime="0"
  298. local _cmd_totaltime="0"
  299. _logger "info" \
  300. "${_FUNCTION_ID}()" \
  301. "init function: '${_args[*]}'"
  302. # In these two variables we store the message to display
  303. # and the command to execute.
  304. export _msg_args=()
  305. export _cmd_args=()
  306. eval "${_args[@]}" ; if [ ! $? ] ; then _exit_ 255 ; fi
  307. _num="${#_msg_args[@]}"
  308. for (( _xa="0" ; _xa<=((_num - 1)) ; _xa++ )) ; do
  309. _msg="${_msg_args[$_xa]}"
  310. _full_command="${_cmd_args[$_xa]}"
  311. _sprintf "info" "$_msg"
  312. _logger "info" \
  313. "${_FUNCTION_ID}()" \
  314. "$_msg"
  315. _cmd_begtime=$(date +%s)
  316. _init_cmd "$_full_command" ; if [ ! "$?" ] ; then _exit_ 255 ; fi
  317. _cmd_endtime=$(date +%s)
  318. # shellcheck disable=SC2154
  319. if [[ "$time_mode" -eq 1 ]] && [[ "$_cmdtime_state" -eq 1 ]] ; then
  320. _cmd_totaltime=$((_cmd_endtime - _cmd_begtime))
  321. _cmd_totaltime_out=$(printf '%dh:%dm:%ds' \
  322. $((_cmd_totaltime/3600)) $((_cmd_totaltime%3600/60)) $((_cmd_totaltime%60)))
  323. _sprintf "info" "time: $_cmd_totaltime_out"
  324. _logger "info" \
  325. "${_FUNCTION_ID}()" \
  326. "time: $_cmd_totaltime_out"
  327. fi
  328. done
  329. _cmdtime_state="0"
  330. return "$_STATE"
  331. }
  332. # ``````````````````````````````````````````````````````````````````````````````
  333. # Function name: _load()
  334. #
  335. # Description:
  336. # Responsible for loading the configuration file, $config variable
  337. # parameter is defined in the script call.
  338. #
  339. # Usage:
  340. # _load "type" "path_to_config_file"
  341. #
  342. # Examples:
  343. # _load "info" "$config"
  344. # _load "head" "/tmp/file.cfg"
  345. #
  346. function _load() {
  347. local _FUNCTION_ID="_load"
  348. local _STATE="0"
  349. local _type="$1"
  350. local _filename="$2"
  351. if [[ ! -z "$_filename" ]] && [[ -e "$_filename" ]] ; then
  352. # If we do not want to inform that the file is loaded,
  353. # the value is 'null', otherwise:
  354. if [[ "$_type" == "head" ]] ; then
  355. _sprintf "head" "load configuration"
  356. _sprintf "info" "file: '$_filename'"
  357. elif [[ "$_type" == "info" ]] ; then
  358. _sprintf "info" "load configuration: '$_filename'"
  359. fi
  360. # shellcheck disable=SC1090
  361. # If the file exists is loaded.
  362. . "$_filename" && \
  363. _logger "info" \
  364. "${_FUNCTION_ID}()" \
  365. "configuration file: '$_filename'"
  366. elif [ -z "$_filename" ] ; then
  367. _sprintf "stop" "incorrectly loaded '$_filename' file (incorrect filename)"
  368. _logger "stop" \
  369. "${_FUNCTION_ID}()" \
  370. "incorrectly loaded '$_filename' file (incorrect filename)"
  371. else
  372. _sprintf "stop" "incorrectly loaded '$_filename' file (does not exist?)"
  373. _logger "stop" \
  374. "${_FUNCTION_ID}()" \
  375. "incorrectly loaded '$_filename' file (does not exist?)"
  376. fi
  377. return "$_STATE"
  378. }
  379. # ``````````````````````````````````````````````````````````````````````````````
  380. # Function name: _help_()
  381. #
  382. # Description:
  383. # Help message. Should be consistent with the contents of the file README.md.
  384. #
  385. # Usage:
  386. # _help_
  387. #
  388. # Examples:
  389. # _help_
  390. #
  391. function _help_() {
  392. local _FUNCTION_ID="_help_"
  393. local _STATE=0
  394. printf "%s" "
  395. Usage:
  396. $_init_name <option|long-option>
  397. Examples:
  398. $_init_name --init 2 --user debian-tor --socks-port 9000 --control-port 9900
  399. $_init_name --init 10 --user debian-tor --socks-port 9000 --control-port 9900 --proxy socks
  400. $_init_name --show-id --socks-port 9000
  401. Options:
  402. --help show this message
  403. --debug displays information on the screen (debug mode)
  404. --verbose displays more information about TOR processes
  405. -i, --init <num> init new tor processes
  406. -k, --kill kill all multitor processes
  407. -s, --show-id show specific tor process id
  408. -n, --new-id regenerate tor circuit
  409. -u, --user <string> set the user (only with -i|--init)
  410. --socks-port <port_num|all> set socks port number
  411. --control-port <port_num> set control port number
  412. --proxy <proxy_type> set socks or http (polipo, privoxy, hpts) proxy server
  413. --haproxy set HAProxy as a frontend for http proxies (only with --proxy)
  414. This program comes with ABSOLUTELY NO WARRANTY.
  415. This is free software, and you are welcome to redistribute it
  416. under certain conditions; for more details please see
  417. <http://www.gnu.org/licenses/>.
  418. "
  419. return $_STATE
  420. }
  421. # ``````````````````````````````````````````````````````````````````````````````
  422. # Function name: _before_init()
  423. #
  424. # Description:
  425. # INFOs performed before calling the __main__ function, e.g.
  426. # attaching files, cleaning logs (if you need a function that will deal
  427. # with it, put it here).
  428. #
  429. # Usage:
  430. # _before_init
  431. #
  432. # Examples:
  433. # _before_init
  434. #
  435. function _before_init() {
  436. local _FUNCTION_ID="_before_init"
  437. local _STATE=0
  438. # shellcheck disable=2154
  439. cd "$_init_directory" || \
  440. _logger "stop" \
  441. "${_FUNCTION_ID}()" \
  442. "directory change error: '$_init_directory'"
  443. : >"$_log_stdout"
  444. # shellcheck disable=2154
  445. if [[ ! -d "$_multitor_directory" && ! -L "$_multitor_directory" ]] ; then
  446. _logger "info" \
  447. "${_FUNCTION_ID}()" \
  448. "creating a multitor directory: '$_multitor_directory'"
  449. mkdir -m 0700 "$_multitor_directory" >>"$_log_stdout" 2>&1
  450. _kstate="$?"
  451. if [[ $_kstate -eq 0 ]] ; then
  452. # shellcheck disable=2154
  453. _logger "info" \
  454. "${_FUNCTION_ID}()" \
  455. "created tor process directory: ${_multitor_directory}"
  456. chown -R "${user_name}" "${_multitor_directory}" >>"$_log_stdout" 2>&1
  457. _kstate="$?"
  458. if [[ $_kstate -eq 0 ]] ; then
  459. _logger "info" \
  460. "${_FUNCTION_ID}()" \
  461. "changed owner properly to: ${_multitor_directory}"
  462. else
  463. _logger "warn" \
  464. "${_FUNCTION_ID}()" \
  465. "the owner could not be changed"
  466. fi
  467. else
  468. _logger "warn" \
  469. "${_FUNCTION_ID}()" \
  470. "not created tor process directory"
  471. fi
  472. else
  473. _multitor_directory_owner=$(stat -c %U "$_multitor_directory")
  474. if [[ "$init_state" -eq 1 ]] ; then
  475. if [[ "$_multitor_directory_owner" != "$user_name" ]] ; then
  476. _sprintf "stop" "bad multitor directory owner"
  477. _logger "stop" \
  478. "${_FUNCTION_ID}()" \
  479. "bad multitor directory owner"
  480. fi
  481. fi
  482. fi
  483. # Flush etc/ directory.
  484. rm -fr "${_etc:?}"/*
  485. return $_STATE
  486. }
  487. # ``````````````````````````````````````````````````````````````````````````````
  488. # Function name: _after_init()
  489. #
  490. # Description:
  491. # INFOs performed after calling the __main__ function, e.g.
  492. # cleaning logs (if you need a function that will deal with it,
  493. # put it here).
  494. #
  495. # Usage:
  496. # _after_init
  497. #
  498. # Examples:
  499. # _after_init
  500. #
  501. function _after_init() {
  502. local _FUNCTION_ID="_after_init"
  503. local _STATE=0
  504. cd "$_init_directory" || \
  505. _logger "stop" \
  506. "${_FUNCTION_ID}()" \
  507. "directory change error: '$_init_directory'"
  508. return $_STATE
  509. }