start-browser 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. #!/usr/bin/env bash
  2. #
  3. # GNU/Linux does not really require something like RelativeLink.c
  4. # However, we do want to have the same look and feel with similar features.
  5. #
  6. # Copyright 2017 The Tor Project. See LICENSE for licensing information.
  7. complain_dialog_title="[% c('var/Project_Name') %]"
  8. # Make sure this script wasn't started as 'sh start-[% c('var/project-name') %]' or similar.
  9. if [ "x$BASH" = "x" ]; then
  10. echo "$complain_dialog_title should be started as './start-[% c('var/project-name') %]'"
  11. echo "Exiting." >&2
  12. exit 1;
  13. fi
  14. # Do not (try to) connect to the session manager
  15. unset SESSION_MANAGER
  16. # Complain about an error, by any means necessary.
  17. # Usage: complain message
  18. # message must not begin with a dash.
  19. complain () {
  20. # Trim leading newlines, to avoid breaking formatting in some dialogs.
  21. complain_message="`echo "$1" | sed '/./,$!d'`"
  22. # If we're being run in debug/verbose mode, complain to stderr.
  23. if [ "$show_output" -eq 1 ]; then
  24. echo "$complain_message" >&2
  25. return
  26. fi
  27. # Otherwise, we're being run by a GUI program of some sort;
  28. # try to pop up a message in the GUI in the nicest way
  29. # possible.
  30. #
  31. # In mksh, non-existent commands return 127; I'll assume all
  32. # other shells set the same exit code if they can't run a
  33. # command. (xmessage returns 1 if the user clicks the WM
  34. # close button, so we do need to look at the exact exit code,
  35. # not just assume the command failed to display a message if
  36. # it returns non-zero.)
  37. # First, try zenity.
  38. zenity --error \
  39. --title="$complain_dialog_title" \
  40. --text="$complain_message"
  41. if [ "$?" -ne 127 ]; then
  42. return
  43. fi
  44. # Try kdialog.
  45. kdialog --title "$complain_dialog_title" \
  46. --error "$complain_message"
  47. if [ "$?" -ne 127 ]; then
  48. return
  49. fi
  50. # Try xmessage.
  51. xmessage -title "$complain_dialog_title" \
  52. -center \
  53. -buttons OK \
  54. -default OK \
  55. -xrm '*message.scrollVertical: Never' \
  56. "$complain_message"
  57. if [ "$?" -ne 127 ]; then
  58. return
  59. fi
  60. # Try gxmessage. This one isn't installed by default on
  61. # Debian with the default GNOME installation, so it seems to
  62. # be the least likely program to have available, but it might
  63. # be used by one of the 'lightweight' Gtk-based desktop
  64. # environments.
  65. gxmessage -title "$complain_dialog_title" \
  66. -center \
  67. -buttons GTK_STOCK_OK \
  68. -default OK \
  69. "$complain_message"
  70. if [ "$?" -ne 127 ]; then
  71. return
  72. fi
  73. }
  74. if [ "`id -u`" -eq 0 ]; then
  75. complain "The [% c('var/Project_Name') %] should not be run as root. Exiting."
  76. exit 1
  77. fi
  78. if uname -m | grep -q -e "x86_64" -e "amd64" -e "i[456]86" ; then
  79. if test -r /proc/cpuinfo && ! grep -q '^flags\s*:.* sse2' /proc/cpuinfo; then
  80. complain "[% c('var/Project_Name') %] requires a CPU with SSE2 support. Exiting."
  81. exit 1
  82. fi
  83. fi
  84. tbb_usage () {
  85. printf "\n[% c('var/Project_Name') %] Script Options\n"
  86. printf " --verbose Display Tor and Firefox output in the terminal\n"
  87. printf " --log [file] Record Tor and Firefox output in file (default: [% c('var/project-name') %].log)\n"
  88. printf " --detach Detach from terminal and run [% c('var/Project_Name') %] in the background.\n"
  89. printf " --register-app Register [% c('var/Project_Name') %] as a desktop app for this user\n"
  90. printf " --unregister-app Unregister [% c('var/Project_Name') %] as a desktop app for this user\n"
  91. }
  92. log_output=0
  93. show_output=0
  94. detach=0
  95. show_usage=0
  96. register_desktop_app=0
  97. logfile=/dev/null
  98. while :
  99. do
  100. case "$1" in
  101. --detach)
  102. detach=1
  103. shift
  104. ;;
  105. -v | --verbose | -d | --debug)
  106. show_output=1
  107. verbose_arg="$2"
  108. shift
  109. ;;
  110. -h | "-?" | --help | -help)
  111. show_usage=1
  112. show_output=1
  113. shift
  114. ;;
  115. -l | --log)
  116. if [ -z "$2" -o "${2:0:1}" == "-" ]; then
  117. printf "Logging [% c('var/Project_Name') %] debug information to [% c('var/project-name') %].log\n"
  118. logfile="../[% c('var/project-name') %].log"
  119. elif [ "${2:0:1}" == "/" -o "${2:0:1}" == "~" ]; then
  120. printf "Logging [% c('var/Project_Name') %] debug information to %s\n" "$2"
  121. logfile="$2"
  122. shift
  123. else
  124. printf "Logging [% c('var/Project_Name') %] debug information to %s\n" "$2"
  125. logfile="../$2"
  126. shift
  127. fi
  128. log_output=1
  129. shift
  130. ;;
  131. --register-app)
  132. register_desktop_app=1
  133. show_output=1
  134. shift
  135. ;;
  136. --unregister-app)
  137. register_desktop_app=-1
  138. show_output=1
  139. shift
  140. ;;
  141. *) # No more options
  142. break
  143. ;;
  144. esac
  145. done
  146. # We can't detach and show output at the same time..
  147. if [ "$show_output" -eq 1 -a "$detach" -eq 1 ]; then
  148. detach=0
  149. fi
  150. if [ "$show_output" -eq 0 ]; then
  151. # If the user hasn't requested 'debug mode' or --help, close stdout and stderr,
  152. # to keep Firefox and the stuff loaded by/for it (including the
  153. # system's shared-library loader) from printing messages to
  154. # $HOME/.xsession-errors or other files. (Users wouldn't have seen
  155. # messages there anyway.)
  156. exec > "$logfile"
  157. exec 2> "$logfile"
  158. fi
  159. # If XAUTHORITY is unset, set it to its default value of $HOME/.Xauthority
  160. # before we change HOME below. (See xauth(1) and #1945.) XDM and KDM rely
  161. # on applications using this default value.
  162. if [ -z "$XAUTHORITY" ]; then
  163. XAUTHORITY=~/.Xauthority
  164. export XAUTHORITY
  165. fi
  166. # If this script is being run through a symlink, we need to know where
  167. # in the filesystem the script itself is, not where the symlink is.
  168. myname="$0"
  169. if [ -L "$myname" ]; then
  170. # XXX readlink is not POSIX, but is present in GNU coreutils
  171. # and on FreeBSD. Unfortunately, the -f option (which follows
  172. # a whole chain of symlinks until it reaches a non-symlink
  173. # path name) is a GNUism, so we have to have a fallback for
  174. # FreeBSD. Fortunately, FreeBSD has realpath instead;
  175. # unfortunately, that's also non-POSIX and is not present in
  176. # GNU coreutils.
  177. #
  178. # If this launcher were a C program, we could just use the
  179. # realpath function, which *is* POSIX. Too bad POSIX didn't
  180. # make that function accessible to shell scripts.
  181. # If realpath is available, use it; it Does The Right Thing.
  182. possibly_my_real_name="`realpath "$myname" 2>/dev/null`"
  183. if [ "$?" -eq 0 ]; then
  184. myname="$possibly_my_real_name"
  185. else
  186. # realpath is not available; hopefully readlink -f works.
  187. myname="`readlink -f "$myname" 2>/dev/null`"
  188. if [ "$?" -ne 0 ]; then
  189. # Ugh.
  190. complain "start-[% c('var/project-name') %] cannot be run using a symlink on this operating system."
  191. fi
  192. fi
  193. fi
  194. # Try to be agnostic to where we're being started from, chdir to where
  195. # the script is.
  196. mydir="`dirname "$myname"`"
  197. test -d "$mydir" && cd "$mydir"
  198. # If ${PWD} results in a zero length string, we can try something else...
  199. if [ ! "${PWD}" ]; then
  200. # "hacking around some braindamage"
  201. PWD="`pwd`"
  202. surveysays="This system has a messed up shell.\n"
  203. fi
  204. # This is a fix for an ibus issue on some Linux systems. See #9353 for more
  205. # details. The symlink needs to be created before we change HOME.
  206. if [ ! -d ".config/ibus" ]; then
  207. mkdir -p .config/ibus
  208. ln -nsf ~/.config/ibus/bus .config/ibus
  209. fi
  210. # Fix up .desktop Icon and Exec Paths, and update the .desktop file from the
  211. # canonical version if it was changed by the updater.
  212. cp start-[% c('var/project-name') %].desktop ../
  213. sed -i -e "s,^Name=.*,Name=[% c('var/Project_Name') %],g" ../start-[% c('var/project-name') %].desktop
  214. sed -i -e "s,^Icon=.*,Icon=$PWD/browser/chrome/icons/default/default128.png,g" ../start-[% c('var/project-name') %].desktop
  215. sed -i -e "s,^Icon=.*,Icon=$PWD/browser/chrome/icons/default/default128.png,g" start-[% c('var/project-name') %].desktop
  216. sed -i -e "s,^Exec=.*,Exec=sh -c '\"$PWD/start-[% c('var/project-name') %]\" --detach || ([ ! -x \"$PWD/start-[% c('var/project-name') %]\" ] \&\& \"\$(dirname \"\$*\")\"/Browser/start-[% c('var/project-name') %] --detach)' dummy %k,g" ../start-[% c('var/project-name') %].desktop
  217. if [ "$register_desktop_app" -eq 1 ]; then
  218. mkdir -p "$HOME/.local/share/applications/"
  219. cp ../start-[% c('var/project-name') %].desktop "$HOME/.local/share/applications/"
  220. update-desktop-database "$HOME/.local/share/applications/"
  221. printf "[% c('var/Project_Name') %] has been registered as a desktop app for this user in ~/.local/share/applications/\n"
  222. exit 0
  223. fi
  224. if [ "$register_desktop_app" -eq -1 ]; then
  225. if [ -e "$HOME/.local/share/applications/start-[% c('var/project-name') %].desktop" ]; then
  226. rm -f "$HOME/.local/share/applications/start-[% c('var/project-name') %].desktop"
  227. update-desktop-database "$HOME/.local/share/applications/"
  228. printf "[% c('var/Project_Name') %] has been removed as a user desktop app (from ~/.local/share/applications/)\n"
  229. else
  230. printf "[% c('var/Project_Name') %] does not appear to be a desktop app (not present in ~/.local/share/applications/)\n"
  231. fi
  232. exit 0
  233. fi
  234. HOME="${PWD}"
  235. export HOME
  236. [% IF c("var/tor-browser") -%]
  237. SYSARCHITECTURE=$(getconf LONG_BIT)
  238. TORARCHITECTURE=$(expr "$(file TorBrowser/Tor/tor)" : '.*ELF \([[:digit:]]*\)')
  239. if [ $SYSARCHITECTURE -ne $TORARCHITECTURE ]; then
  240. complain "Wrong architecture? 32-bit vs. 64-bit."
  241. exit 1
  242. fi
  243. [% END -%]
  244. [% IF c("var/asan") -%]
  245. # We need to disable LSan which is enabled by default now. Otherwise we'll get
  246. # a crash during shutdown: https://bugs.torproject.org/10599#comment:59
  247. ASAN_OPTIONS="detect_leaks=0"
  248. export ASAN_OPTIONS
  249. [% END -%]
  250. [% IF c("var/tor-browser") -%]
  251. function setControlPortPasswd() {
  252. local ctrlPasswd=$1
  253. if test -z "$ctrlPasswd" -o "$ctrlPasswd" = $'\"secret\"' ; then
  254. unset TOR_CONTROL_PASSWD
  255. return
  256. fi
  257. if test "${ctrlPasswd:0:1}" = $'\"'; then # First 2 chars were '"
  258. printf "Using system Tor process.\n"
  259. export TOR_CONTROL_PASSWD
  260. else
  261. complain "There seems to have been a quoting problem with your \
  262. TOR_CONTROL_PASSWD environment variable."
  263. echo "The Tor ControlPort password should be given inside double"
  264. echo "quotes, inside single quotes. That is, if the ControlPort"
  265. echo 'password is “secret” (without curly quotes) then we must'
  266. echo "start this script after setting the environment variable"
  267. echo "exactly like this:"
  268. echo
  269. echo " \$ TOR_CONTROL_PASSWD='\"secret\"' $myname"
  270. fi
  271. }
  272. # Using a system-installed Tor process with Tor Browser:
  273. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  274. # The Tor ControlPort password should be given inside double quotes, inside
  275. # single quotes, i.e. if the ControlPort password is “secret” (without
  276. # curly quotes) then we must set the environment variable *exactly* like
  277. # this:
  278. #
  279. # TOR_CONTROL_PASSWD='"secret"'
  280. #
  281. # Yes, the variable MUST be double-quoted, then single-quoted, exactly as
  282. # shown. This is used by TorButton and Tor Launcher to authenticate to Tor's
  283. # ControlPort, and is necessary for using TB with a system-installed Tor.
  284. #
  285. # Additionally, if using a system-installed Tor, the following about:config
  286. # options should be set (values in <> mean they are the value taken from your
  287. # torrc):
  288. #
  289. # SETTING NAME VALUE
  290. # network.proxy.socks 127.0.0.1
  291. # network.proxy.socks_port <SocksPort>
  292. # extensions.torbutton.inserted_button true
  293. # extensions.torbutton.launch_warning false
  294. # extensions.torbutton.loglevel 2
  295. # extensions.torbutton.logmethod 0
  296. # extensions.torlauncher.control_port <ControlPort>
  297. # extensions.torlauncher.loglevel 2
  298. # extensions.torlauncher.logmethod 0
  299. # extensions.torlauncher.prompt_at_startup false
  300. # extensions.torlauncher.start_tor false
  301. #
  302. # where the '[...]' in the banned_ports option means "leave anything that was
  303. # already in the preference alone, just append the things specified after it".
  304. # Either set `TOR_CONTROL_PASSWD` before running ./start-tor-browser, or put
  305. # your password in the following line where the word “secret” is:
  306. setControlPortPasswd ${TOR_CONTROL_PASSWD:='"secret"'}
  307. [% END -%]
  308. # Set up custom bundled fonts. See fonts-conf(5).
  309. export FONTCONFIG_PATH="${HOME}/[% c('var/ProjectName') %]/Data/fontconfig"
  310. export FONTCONFIG_FILE="fonts.conf"
  311. # Avoid overwriting user's dconf values. Fixes #27903.
  312. export GSETTINGS_BACKEND=memory
  313. cd "${HOME}"
  314. # We pass all additional command-line arguments we get to Firefox.
  315. #
  316. # The --class parameter was added to fix bug trac#11102 (X11).
  317. # The --name parameter was added to fix bug tor-browser-build#40517 (Wayland).
  318. # --class and --name parameters are used to make sure WM_CLASS is set
  319. # up correctly, to identify itself from plain Firefox windows (and
  320. # prevent from mixing up with them).
  321. if [ "$show_usage" -eq 1 ]; then
  322. # Display Firefox help, then our help
  323. [% IF c("var/tor-browser") %]TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD}[% END %] ./firefox \
  324. --class "[% c('var/Project_Name') %]" --name "[% c('var/Project_Name') %]" \
  325. -profile [% c('var/ProjectName') %]/Data/Browser/profile.default --help 2>/dev/null
  326. tbb_usage
  327. elif [ "$detach" -eq 1 ] ; then
  328. [% IF c("var/tor-browser") %]TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD}[% END %] ./firefox \
  329. --class "[% c('var/Project_Name') %]" --name "[% c('var/Project_Name') %]" \
  330. -profile [% c('var/ProjectName') %]/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null &
  331. disown "$!"
  332. elif [ "$log_output" -eq 1 -a "$show_output" -eq 1 ]; then
  333. [% IF c("var/tor-browser") %]TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD}[% END %] ./firefox \
  334. --class "[% c('var/Project_Name') %]" --name "[% c('var/Project_Name') %]" \
  335. -profile [% c('var/ProjectName') %]/Data/Browser/profile.default "${@}" 2>&1 </dev/null | \
  336. tee "$logfile"
  337. elif [ "$show_output" -eq 1 ]; then
  338. [% IF c("var/tor-browser") %]TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD}[% END %] ./firefox \
  339. --class "[% c('var/Project_Name') %]" --name "[% c('var/Project_Name') %]" \
  340. -profile [% c('var/ProjectName') %]/Data/Browser/profile.default "${@}" < /dev/null
  341. else
  342. [% IF c("var/tor-browser") %]TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD}[% END %] ./firefox \
  343. --class "[% c('var/Project_Name') %]" --name "[% c('var/Project_Name') %]" \
  344. -profile [% c('var/ProjectName') %]/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null
  345. fi
  346. exit $?