Fix incorrect use of variable
[chere.git] / src / chere
blobc596f345042f7f6c24b3c3a91d023eea8ac3eb46
1 #!/bin/bash
3 # This shell script manages Cygwin Prompt Here functionality.
4 # Requires: regtool, uname, id, cygpath, bash, sed, wc
6 # TODO
7 # ----
8 # 1. Use runas to make sure regtool has the right privileges when installing for all users
9 # Would need to call myself with runas so the user only enters pwd once.
10 # 2. Warn if using -2 without appropriate login shell modifications.
12 # KNOWN ERRORS
14 # cmd and command terminals cannot cd to network paths like \\server\share.
16 # Dave Kilroy
17 # Nov 2011
19 VERSION=1.4
20 # Canonical repository at
21 # git://repo.or.cz/chere.git
22 # http://repo.or.cz/r/chere.git
24 # HISTORY PRIOR TO GIT
25 #VERSION=1.2
26 # Support 64-bit windows.
27 # Support for urxvt terminal.
28 # Support for dash shell.
29 # Support for mksh shell.
30 #VERSION=1.1
31 # Add support for the posh shell
32 # Add support for the mintty terminal.
33 #VERSION=1.0
34 # Option to add to the terminal startup command.
35 # Option to specify context menu text.
36 # Together these options allow you to add a context menu to start
37 # named terminals (that have different properties, configured in
38 # .Xdefaults).
39 # Revert to using bash getopts to handle spaces in new options arguments.
40 #VERSION=0.8
41 # Set path and DISPLAY for xterm
42 # Thanks to Lewis Hyatt for pointing this out and Paul Mallas for
43 # identifying the -display option.
44 # Fix find_term_of_installed_shell so it copes better if the command
45 # is not in the precise format we expect.
46 #VERSION=0.7
47 # Abort registry key removal as soon as we notice a non-empty key
48 # Print help immediately if no action
49 # Make context menu text clearer
50 # Thanks to Brian Mathis
51 #VERSION=0.6-1
52 # Correct bad function call to get_shell_from_passwd
53 # Thanks to Dave Griffin
54 #VERSION=0.6
55 # Restructure to use shell functions
56 # Add version option
57 # Add -x option to update current entries
58 # Enter correct directory when using the RH pane
59 # Thanks to Nils Jeppe
60 #VERSION=0.5
61 # Add back -a and -c options to set options in HKCU
62 # Make sure the appropriate entries are uninstalled when run.
63 # (Obey -a and -c options)
64 # Note a user can't uninstall for another user
65 # Remove reference to -x that sneaked into help
66 # Rationalize help as chere now has a man page
67 # sed now required to parse XX_KEYS and ensure they exist
68 #VERSION=0.4
69 # Add r to synopsis
70 # Remove redundant TERM_CMDs and CYG_DIR
71 # Use run.exe if I can find it
72 # Add -1 and -2 options to determine how to start the shell. 2 is default
73 # -2 fixes reported issues with network paths and tcsh/ash login shells
74 # Thanks to Igor Petchanksi, Andrew Grimm, Munehiro (haro) Matsuda
75 # -2 untested on XP/NT/95/98/ME
76 #VERSION=0.3
77 # Use forward slashes for command to fix XP problems (CGF)
78 # Correct quoting (CGF)
79 # Add -r option to read registry entries to stdout to help debugging
80 #VERSION=0.2
81 # Use consistent registry key based on shell id
82 # Fixup windows version check
83 # Use correct cmd/command quoting
84 # Add list option, install is no longer default
85 # Check regtool/sed is present
86 # Add xterm -e arg
87 # Check the term/shell is present before installing (except cmd)
88 # Add information on window title and login shells
89 # Set pdksh, tcsh, zsh to start login shells
90 # Case statements ash compatible
91 # Look in passwd for shell if not specified
92 # Mental runtime check of passwd added. Use at own risk
93 # Changed to use getopt and removed [[ ]] tests. Ash compatible.
94 # Updated shebang
95 #VERSION=0.1
96 # Initial implementation.
97 # Bash required.
98 # Possible quoting problems.
99 # Windows uninstall only posible if script present
102 #########################################################################
103 # Define functions (for modularity and readability) #
104 #########################################################################
106 # Prints usage information
107 print_help()
109 cat <<-EOF
110 $0 version $VERSION
112 Usage:
113 $0 -<iuxlrhv> [-lracnmpf12] [-t <term>] [-s <shell>]
114 [-d <display> ] [-o <options>] [-e <menutext>]
116 Adds the stated terminal/shell combination to the folder context menu
117 This allows you to right click a folder in Windows Explorer and open
118 a Cygwin shell in that folder.
120 Options:
121 i - Install
122 u - Uninstall
123 x - Freshen eXisting entries
124 l - List currently installed chere items
125 r - Read all chere registry entries to stdout
126 a - All users
127 c - Current user only
128 n - Be Nice and provide Control Panel uninstall option (Default)
129 m - Minimal, no Control Panel uninstall
130 p - Print regtool commands to stdout rather than running them
131 f - Force write (overwrite existing, ignore missing files)
132 1 - Start using registry one-liners. This doesn't work with ash,
133 tcsh or network shares.
134 2 - Start via bash script. Relies on windows to change directory,
135 and login scripts avoiding doing a cd $HOME
136 h - Help
137 v - Version
139 t <term> - Use terminal term. Supported terminals are:
140 $KNOWN_TERMS
142 s <shell> - Use the named shell. Supported shells are:
143 $KNOWN_SHELLS
145 d <display> - DISPLAY to use (xterm, urxvt). Defaults to :0.
146 Set to env to use the runtime environment variable.
148 o <options> - Add <options> to the terminal startup command.
149 If more than one option is specified, they should all be
150 contained within a single set of quotes.
152 e <menutext> - Use <menutext> as the context menu text.
154 See the man page for more detail.
156 # Handle unclosed quote for syntax highlighting '
159 # Function to verify all required utilies are present
160 # Notes:
161 # Exits if any required utilites are missing
162 check_requirements()
164 # Quick check of common utilities (from sh-utils, cygwin, textutils packages)
165 if [ ! -x /bin/uname ] || [ ! -x /bin/cygpath ] || [ ! -x /bin/id ] || [ ! -x /bin/wc ] || [ ! -x /bin/sed ] ; then
166 echo $0 Error: uname / id / cygpath / wc / sed not found
167 echo
168 echo These tools are required for correct operation.
169 echo $0: Aborting
170 exit
173 # Check we have regtool (from cygwin package)
174 if [ ! -x /bin/regtool ]; then
175 echo $0 Error: /bin/regtool not found
176 echo
177 echo You need regtool installed for this script to work.
178 echo $0: Aborting.
179 exit
184 # Get information about the current system
185 # Sets:
186 # VER - system version
187 # ID_USER - username
188 # RUN_EXE - windows path to run.exe if present
189 # ASH_EXE - windows path to ash if present
190 # BASH_EXE - windows path to bash if present
191 # PFX - registry prefix to use for cygwin keys
192 # DIR_KEY_CU - Registry key for directory context menu for current user
193 # DIR_BG_KEY_CU - and the context menu for the directory background
194 # DRIVE_KEY_CU - Registry key for drive context menu for current user
195 # DRIVE_BG_KEY_CU - and the context menu for the drive background
196 # DIR_KEY_CR - Registry key for directory context menu for all users
197 # DIR_BG_KEY_CR - and the context menu for the directory background
198 # DRIVE_KEY_CR - Registry key for drive context menu for all users
199 # DRIVE_BG_KEY_CR - and the context menu for the drive background
200 # UINST_KEY - Registry key for uninstall information
201 get_system_info()
203 # Check windows version and cygwin install directory
204 VER=`uname -s`
205 ID_USER=`id -nu`
206 RUN_EXE=""
207 ASH_EXE=`cygpath -w /bin/sh`
208 BASH_EXE=`cygpath -w /bin/bash`
210 if [ `uname -m` = "i686" ]; then
211 PFX=cygwin_
212 else
213 PFX=cygwin64_
216 if [ -x /bin/which ]; then
217 # Enable prepending of run.exe if we can find it.
218 # I'm assuming run has been placed in the path.
220 # We did this because run.exe was packaged in X-startup-scripts.
221 # It is now in its own package and part of base.
222 # However, continue to check for it in this way.
224 RUN_EXE=`which run.exe 2>/dev/null`
225 if [ -n "$RUN_EXE" ]; then
226 # Convert to windows path
227 RUN_EXE=`cygpath -w "$RUN_EXE"`
231 # Identify the registry keys for each OS and desired set of users
232 # Same for all?
233 # Note that the entry /HKCU/Software/Classes may not exist, and may need
234 # to be created for the user.
235 DIR_KEY_CR=/HKCR/Directory/Shell
236 DIR_BG_KEY_CR=/HKCR/Directory/Background/Shell
237 DRIVE_KEY_CR=/HKCR/Drive/Shell
238 DRIVE_BG_KEY_CR=/HKCR/Drive/Background/Shell
239 DIR_KEY_CU=/HKCU/Software/Classes/Directory/Shell
240 DIR_BG_KEY_CU=/HKCU/Software/Classes/Directory/Background/Shell
241 DRIVE_KEY_CU=/HKCU/Software/Classes/Drive/Shell
242 DRIVE_BG_KEY_CU=/HKCU/Software/Classes/Drive/Background/Shell
243 UINST_KEY=/HKLM/Software/Microsoft/Windows/CurrentVersion/Uninstall
246 # Selects the registry entries to use based on action and user.
247 # Arguments:
248 # $1 - Action. If install output keys to install for. Otherwise keys to remove
249 # $2 - If TRUE (not f), set for all users.
250 # Otherwise, set for current user.
251 # Sets:
252 # DIR_KEY - Registry key for directory context menu
253 # DIR_BG_KEY - Registry key for the directory background context menu
254 # DRIVE_KEY - Registry key for drive context menu
255 # DRIVE_BG_KEY - Registry key for the drive background context menu
256 # DIR_KEYS - Registry keys to be removed (directory)
257 # DRIVE_KEYS - Registry keys to be removed (drive)
258 # UINST_ARG - Argument to pass to chere on uninstall
259 # Refers to:
260 # DIR_KEY_CU - Registry key for directory context menu for current user
261 # DIR_BG_KEY_CU - and the context menu for the directory background
262 # DRIVE_KEY_CU - Registry key for drive context menu for current user
263 # DRIVE_BG_KEY_CU - and the context menu for the drive background
264 # DIR_KEY_CR - Registry key for directory context menu for all users
265 # DIR_BG_KEY_CR - and the context menu for the directory background
266 # DRIVE_KEY_CR - Registry key for drive context menu for all users
267 # DRIVE_BG_KEY_CR - and the context menu for the drive background
268 set_for_user()
270 if [ $1 = i ]; then
271 # Set for install
272 if [ $2 = f ]; then
273 DIR_KEY=$DIR_KEY_CU
274 DIR_BG_KEY=$DIR_BG_KEY_CU
275 DRIVE_KEY=$DRIVE_KEY_CU
276 DRIVE_BG_KEY=$DRIVE_BG_KEY_CU
277 UINST_ARG="-c"
278 else
279 # all users is the default
280 DIR_KEY=$DIR_KEY_CR
281 DIR_BG_KEY=$DIR_BG_KEY_CR
282 DRIVE_KEY=$DRIVE_KEY_CR
283 DRIVE_BG_KEY=$DRIVE_BG_KEY_CR
285 else
286 # Set for uninstall
287 if [ $2 = t ]; then
288 # Don't remove HKCU entries
289 DRIVE_KEYS="$DRIVE_KEY_CR $DRIVE_BG_KEY_CR"
290 DIR_KEYS="$DIR_KEY_CR $DIR_BG_KEY_CR"
291 elif [ $2 = f ]; then
292 # Don't remove HKCR entries
293 DRIVE_KEYS="$DRIVE_KEY_CU $DRIVE_BG_KEY_CU"
294 DIR_KEYS="$DIR_KEY_CU $DIR_BG_KEY_CU"
295 else
296 # Else remove both HKCR and HKCU entries
297 DRIVE_KEYS="$DRIVE_KEY_CR $DRIVE_KEY_CU $DRIVE_BG_KEY_CR $DRIVE_BG_KEY_CU"
298 DIR_KEYS="$DIR_KEY_CR $DIR_KEY_CU $DIR_BG_KEY_CR $DIR_BG_KEY_CU"
303 # Returns users shell, based on their passwd entry
304 # Uses:
305 # ID_USER - current user
306 get_shell_from_passwd()
308 getent passwd $ID_USER | sed -n "s?.*:/bin/\(.*\)?\1?gp"
311 # Identifies the terminal installed for the named shell
312 # Parameters:
313 # $1 - shell
314 # Uses:
315 # DIR_KEY - Registry base to find shell entry
316 # PFX - Registry prefix to use for cygwin keys
317 find_term_of_installed_shell()
319 local KEY_VALUE TERM_REGEXP
321 # use sed to strip everything except known terminals
322 # construct the regexp of known terminals from KNOWN_TERMS
323 # add command as well to pick up on 9x
324 TERM_REGEXP=`echo $KNOWN_TERMS command | sed 's/ \+/\\\\|/g'`
325 KEY_VALUE=`$REGTOOL_ get $DIR_KEY/$PFX$1/command/ | sed "s/.*\($TERM_REGEXP\).*/\1/g"`
327 if [ "$KEY_VALUE" = "command" ]; then
328 KEY_VALUE=cmd
330 echo $KEY_VALUE
333 # Setup to install for a particular terminal
334 # Arguments:
335 # $1 - term to setup for
336 # Sets:
337 # TERM_EXE - path to terminals executable
338 # TERM_ARGS - arguments to pass to the terminal
339 # RUN_ARGS - arguments to pass to run.exe
340 # Uses:
341 # VER - OS version
342 # KNOWN_TERMS - list of known terminals
343 # DISP - display to use for xterm
344 # USER_TERM_OPTIONS - users custom options for terminal
345 # Notes:
346 # Exits if term is not recognised
347 setup_for_term()
349 #################### Define terminals ########################
350 # For each terminal, indicate the executable in TERM_EXE.
351 # Unless it is cmd, it is assumed that -e passes the startup
352 # command
353 TERM_ARGS=""
354 RUN_ARGS=""
355 case $1 in
356 cmd )
357 case $VER in
358 CYGWIN_NT* )
359 TERM_EXE=cmd.exe;;
361 TERM_EXE=command.com;;
362 esac
363 TERM_ARGS="$USER_TERM_OPTIONS";;
364 rxvt )
365 TERM_EXE="/bin/rxvt.exe"
366 TERM_ARGS="$USER_TERM_OPTIONS";;
367 urxvt )
368 TERM_EXE="/bin/urxvt"
369 TERM_ARGS="-display $DISP $USER_TERM_OPTIONS";;
370 mintty )
371 TERM_EXE="/bin/mintty.exe"
372 TERM_ARGS="$USER_TERM_OPTIONS"
373 RUN_EXE="";; # For some reason run.exe breaks mintty
374 xterm )
375 TERM_EXE="/bin/xterm.exe"
376 TERM_ARGS="-display $DISP $USER_TERM_OPTIONS"
377 RUN_ARGS="-p /usr/X11R6/bin";;
379 echo $0 Error: Unknown terminal $this_term
380 echo
381 echo Supported terminals:
382 echo $KNOWN_TERMS
383 echo
384 echo Use -h for help
385 exit;;
386 esac
389 # Setup to install a particular shell.
390 # Arguments:
391 # $1 - shell to install
392 # Sets:
393 # SHELL_EXE - path to shell executable
394 # SHELL_CMD - argument to pass to shell executable (Method 1 only)
395 # ACCEL - context menu text
396 # CPH_DESC - description for uninstall
397 # Uses:
398 # VER - OS version
399 # FORCE - set to t to force installation of passwd in its absence
400 # KNOWN_SHELLS - list of known shells
401 # USER_MENU_TEXT - User specified menu text
402 # ID_USER - current user
404 # Notes:
405 # If shell is passwd, checks for the presence of /etc/passwd
406 # Exits if shell is passwd, /etc/passwd not found and FORCE is not t.
407 # Exits if shell is not recognised
408 setup_for_shell()
410 local ge_shell
412 #################### Define shells #############################
413 # For each shell, specify:
414 # the location of the executable to be checked on install
415 # the arguments that should be used to start it in the directory %1, and keep it open.
416 # the accelerator to be displayed on the menu
417 # the description text to be displayed in control panel uninstall window
418 case $1 in
419 bash )
420 SHELL_EXE="/bin/bash.exe"
421 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
422 ACCEL="&Bash Prompt Here"
423 CPH_DESC="Cygwin Bash Prompt Here";;
424 ash )
425 # TODO How to make this a login shell? Is -l undocumented?
426 SHELL_EXE="/bin/sh.exe"
427 SHELL_CMD="-c \\\"cd '%L'; exec $SHELL_EXE\\\"";
428 ACCEL="&Ash Prompt Here"
429 CPH_DESC="Cygwin Ash Prompt Here";;
430 pdksh )
431 SHELL_EXE="/bin/pdksh.exe"
432 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
433 ACCEL="&Pdksh Prompt Here"
434 CPH_DESC="Cygwin Pdksh Prompt Here";;
435 posh )
436 SHELL_EXE="/bin/posh.exe"
437 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
438 ACCEL="&Posh Prompt Here"
439 CPH_DESC="Cygwin Posh Prompt Here";;
440 tcsh )
441 # Apparently -l only applies if it is the only argument
442 # so this may not work
443 SHELL_EXE="/bin/tcsh.exe"
444 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
445 ACCEL="&Tcsh Prompt Here"
446 CPH_DESC="Cygwin Tcsh Prompt Here";;
447 zsh )
448 SHELL_EXE="/bin/zsh.exe"
449 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
450 ACCEL="&Zsh Prompt Here"
451 CPH_DESC="Cygwin Zsh Prompt Here";;
452 dash )
453 SHELL_EXE="/bin/dash.exe"
454 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
455 ACCEL="&Dash Prompt Here"
456 CPH_DESC="Cygwin Dash Prompt Here";;
457 mksh )
458 SHELL_EXE="/bin/mksh.exe"
459 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
460 ACCEL="&Mksh Prompt Here"
461 CPH_DESC="Cygwin Mksh Prompt Here";;
462 fish )
463 SHELL_EXE="/bin/fish"
464 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
465 ACCEL="&Fish Prompt Here"
466 CPH_DESC="Cygwin Fish Prompt Here";;
467 cmd )
468 case $VER in
469 CYGWIN_NT* )
470 SHELL_EXE=cmd.exe
471 SHELL_CMD="/k cd /d \\\"%L\\\"";;
473 SHELL_EXE=command.com
474 SHELL_CMD="/k cd \\\"%1\\\"";;
475 esac
476 ACCEL="&Command Prompt Here"
477 CPH_DESC="Command Prompt Here (cygwin)";;
478 passwd )
479 # Experimental
480 SHELL_EXE="/bin/sh"
481 # Quoting nightmare. Step through it all
482 # c:\cygwin\bin\sh -c "scmd=`getent passwd \`id -un\` | sed -n \"s?.*:\\\(.*\\\)?\\\1?gp\"`; $scmd -l -c \"cd 'c:/program files'; exec $scmd\""
483 # works from the command line
484 # In registry it needs to read the same:
485 # c:\cygwin\bin\sh -c "scmd=`getent passwd \`id -un\` | sed -n \"s?.*:\\\(.*\\\)?\\\1?gp\"`; $scmd -l -c \"cd '%L'; exec $scmd\""
486 # When passed to regtool, need to requote for the shell:
487 # "c:\cygwin\bin\sh -c \"scmd=\`getent passwd \\\`id -un\\\` | sed -n \\\"s?.*:\\\\\\(.*\\\\\\)?\\\\\\1?gp\\\"\`; \$scmd -l -c \\\"cd '%L'; exec \$scmd\\\"\""
488 # When evaluated into a variable, need another level of quoting:
489 # "c:\cygwin\bin\sh -c \\\"scmd=\\\`getent passwd \\\\\\\`id -un\\\\\\\` | sed -n \\\\\\\"s?.*:\\\\\\\\\\\\(.*\\\\\\\\\\\\)?\\\\\\\\\\\\1?gp\\\\\\\"\\\`; \\\$scmd -l -c \\\\\\\"cd '%L'; exec \\\$scmd\\\\\\\"\\\""
490 # Ouch. If you think it can be quoted better, let me know.
491 SHELL_CMD="-c \\\"scmd=\\\`getent passwd \\\\\\\`id -un\\\\\\\` | sed -n \\\\\\\"s?.*:\\\\\\\\\\\\(.*\\\\\\\\\\\\)?\\\\\\\\\\\\1?gp\\\\\\\"\\\`; \\\$scmd -l -c \\\\\\\"cd '%L'; exec \\\$scmd\\\\\\\"\\\""
492 ACCEL="Shell Prompt &Here"
493 CPH_DESC="Cygwin Prompt Here"
495 # Extra check before installing passwd
496 ge_shell=`get_shell_from_passwd`
497 if [ -z "$ge_shell" ]; then
498 if [ $FORCE = t ]; then
499 echo $0 Warning: login shell has not been set for user $ID_USER
500 echo
501 echo This is required for the runtime context menu item to work.
502 echo See cygwin documentation on how to set the login shell.
503 else
504 echo $0 Error: login shell has not been set for user $ID_USER
505 echo
506 echo This is required for the runtime context menu item to work.
507 echo See cygwin documentation on how to set the login shell.
508 echo Use -f to install anyway.
509 exit
511 fi;;
513 echo $0 Error: Unknown shell $1
514 echo
515 echo Supported shells:
516 echo $KNOWN_SHELLS
517 echo
518 echo Use -h for help
519 exit;;
520 esac
522 # Uninstall string should indicate 64 or 32 bit cygwin entry
523 if [ `uname -m` = "i686" ]; then
524 CPH_DESC+=" (x86)"
525 else
526 CPH_DESC+=" (x86_64)"
529 # Override standard accelerator if specified
530 if [ -n "$USER_MENU_TEXT" ] ; then
531 ACCEL="$USER_MENU_TEXT"
535 # Builds the command to execute when the context menu item is selected
536 # Arguments:
537 # $1 - Terminal to use
538 # $2 - Shell to install
539 # $3 - Method used to invoke term/shell combo
540 # Sets:
541 # START_CMD - command to execute
542 # SHELL_EXE - modified if this_shell is passwd and using method 2
543 # SHELL_CMD - cleared if using method 2
544 # SHELL_BG_CMD - command to use from background pane
545 # Uses:
546 # RUN_EXE - location of run.exe if present
547 # RUN_ARGS - argument to pass to run.exe
548 # TERM_EXE - location of terminal executable
549 # TERM_ARGS - arguments to pass to reminal
550 # SHELL_EXE - location of shell executable
551 build_start_cmd()
553 local TERM_WIN_EXE XHERE
554 # TERM_EXE needs to be called by a windows path, even from run.exe
555 TERM_WIN_EXE=`cygpath -w "$TERM_EXE"`
556 if [ $3 = 1 ]; then
557 # METHOD 1 - invoke term and shell directly from the registry
558 if [ $1 != cmd ]; then
559 if [ -n "$RUN_EXE" ]; then
560 START_CMD="$RUN_EXE $RUN_ARGS $TERM_WIN_EXE $TERM_ARGS -e $SHELL_EXE"
561 else
562 START_CMD="$TERM_WIN_EXE $TERM_ARGS -e $SHELL_EXE"
564 elif [ $2 != cmd ]; then
565 # With cmd (term), the shell executable needs to be converted
566 # to a windows path
567 # With cmd, we ignore TERM_CMD.
568 START_CMD=`cygpath -w "$SHELL_EXE"`
569 else
570 # term and shell are cmd
571 START_CMD=$SHELL_EXE
573 else
574 # METHOD 2 - invoke xhere from the registry
575 XHERE="/bin/xhere"
576 if [ $2 = cmd ]; then
577 # Clear XHERE for when running command from rxvt/xterm
578 XHERE="";
579 elif [ $2 = passwd ]; then
580 # Have XHERE do the call rather than bung it in the registry
581 SHELL_EXE="/etc/passwd"
584 if [ $1 != cmd ]; then
585 if [ -n "$RUN_EXE" ]; then
586 START_CMD="$RUN_EXE $RUN_ARGS $TERM_WIN_EXE $TERM_ARGS -e $XHERE $SHELL_EXE"
587 else
588 START_CMD="$TERM_WIN_EXE $TERM_ARGS -e $XHERE $SHELL_EXE"
590 if [ $2 != cmd ]; then
591 SHELL_CMD="\\\"%L\\\""
592 SHELL_BG_CMD="\\\"%V\\\""
594 elif [ $2 != cmd ]; then
595 START_CMD="`cygpath -w \"$BASH_EXE\"`"
596 SHELL_CMD="-c \\\"$XHERE $SHELL_EXE '%L'\\\""
597 SHELL_BG_CMD="-c \\\"$XHERE $SHELL_EXE '%V'\\\""
598 else
599 # The command shell won't cd anywhere anyway
600 START_CMD=$SHELL_EXE
605 # Create full path to registry key
606 # Arguments:
607 # $1 - Registry key to create
608 # Notes:
609 # Exits if key cannot be created
610 create_registry_key()
612 local KEY_ELEMENTS CUR_KEY
613 KEY_ELEMENTS=`echo $1 | sed "s?/? ?g"`
614 CUR_KEY=
615 for elem in $KEY_ELEMENTS; do
616 CUR_KEY=$CUR_KEY/$elem
617 if ! $REGTOOL_ check $CUR_KEY 2>/dev/null ; then
618 # elem not present, so add it
619 if ! $REGTOOL add $CUR_KEY ; then
620 echo $0 Error: Hive not writable
621 echo $0: Aborting.
622 exit
625 done
628 # Removes a key and any empty parents
629 # $1 - key to remove
630 remove_registry_key()
632 local CUR_KEY ENTRIES
633 CUR_KEY=$1
634 if $REGTOOL_ check $CUR_KEY 2> /dev/null; then
635 while [ -n "$CUR_KEY" ]; do
636 ENTRIES=`$REGTOOL_ list $CUR_KEY | wc -l`
637 if [ $ENTRIES = "0" ] || ( [ $ENTRIES = "1" ] && [ $PRINT = t ] ); then
638 # Remove empty key
639 $REGTOOL remove $CUR_KEY
640 CUR_KEY=`echo $CUR_KEY | sed "s?/[^/]*\\$??g"`
641 else
642 # Abort
643 CUR_KEY=
645 done
649 # Print registry keys and values that chere knows about
650 # Uses:
651 # KNOWN_SHELLS - list of known shells
652 # DIR_KEY_CU - Registry key for directory context menu for current user
653 # DRIVE_KEY_CU - Registry key for drive context menu for current user
654 # DIR_KEY_CR - Registry key for directory context menu for all users
655 # DRIVE_KEY_CR - Registry key for drive context menu for all users
656 # UINST_KEY - Registry key for uninstall information
657 # PFX - Registry prefix to use for cygwin keys
658 read_chere_registry_keys()
660 local FOR_WHO=""
661 for shell in $KNOWN_SHELLS; do
662 echo --- $shell keys ---
663 #### Directory entries ####
664 FOR_WHO="(all users)"
665 for dir in $DIR_KEY_CR $DIR_KEY_CU ; do
666 if $REGTOOL_ check $dir/$PFX$shell 2> /dev/null; then
667 echo Directory menu item $FOR_WHO
668 $REGTOOL get $dir/$PFX$shell/
669 echo
671 if $REGTOOL_ check $dir/$PFX$shell/command 2> /dev/null; then
672 echo Directory command $FOR_WHO
673 $REGTOOL get $dir/$PFX$shell/command/
674 echo
676 FOR_WHO="(current user)"
677 done
678 #### Directory background entries ####
679 FOR_WHO="(all users)"
680 for dir in $DIR_BG_KEY_CR $DIR_BG_KEY_CU ; do
681 if $REGTOOL_ check $dir/$PFX$shell 2> /dev/null; then
682 echo Directory background menu item $FOR_WHO
683 $REGTOOL get $dir/$PFX$shell/
684 echo
686 if $REGTOOL_ check $dir/$PFX$shell/command 2> /dev/null; then
687 echo Directory background command $FOR_WHO
688 $REGTOOL get $dir/$PFX$shell/command/
689 echo
691 FOR_WHO="(current user)"
692 done
693 #### Drive entries ####
694 FOR_WHO="(all users)"
695 for drive in $DRIVE_KEY_CR $DRIVE_KEY_CU ; do
696 if $REGTOOL_ check $drive/$PFX$shell 2> /dev/null; then
697 echo Drive menu item $FOR_WHO
698 $REGTOOL get $drive/$PFX$shell/
699 echo
701 if $REGTOOL_ check $drive/$PFX$shell/command 2> /dev/null; then
702 echo Drive command $FOR_WHO
703 $REGTOOL get $drive/$PFX$shell/command/
704 echo
706 FOR_WHO="(current user)"
707 done
708 #### Drive background entries ####
709 FOR_WHO="(all users)"
710 for drive in $DRIVE_BG_KEY_CR $DRIVE_BG_KEY_CU ; do
711 if $REGTOOL_ check $drive/$PFX$shell 2> /dev/null; then
712 echo Drive background menu item $FOR_WHO
713 $REGTOOL get $drive/$PFX$shell/
714 echo
716 if $REGTOOL_ check $drive/$PFX$shell/command 2> /dev/null; then
717 echo Drive background command $FOR_WHO
718 $REGTOOL get $drive/$PFX$shell/command/
719 echo
721 FOR_WHO="(current user)"
722 done
723 #### UnInstall entries ####
724 if $REGTOOL_ check $UINST_KEY/$PFX$shell 2> /dev/null; then
725 echo Uninstall description
726 $REGTOOL get $UINST_KEY/$PFX$shell/DisplayName
727 echo
728 echo Uninstall command
729 $REGTOOL get $UINST_KEY/$PFX$shell/UnInstallString
730 echo
732 echo
733 done
736 # Lists all cygwin items in given registry node to stdout
737 # Parameters:
738 # $1 - Node to search
739 # Uses:
740 # PFX - Registry prefix to use for cygwin keys
741 list_cygwin_registry_keys()
743 $REGTOOL_ list $1 2> /dev/null | sed -n 's/$PFX\(.*\)/\1/gp'
746 # Install keys under $1 for shell $2
747 # Arguments:
748 # $1 - Registry key to create
749 # $2 - Shell being installed
750 # $3 - Accelerator
751 # $4 - Command
752 # Uses:
753 # FORCE
754 install_context_menu()
756 if [ $FORCE = t ] || ! $REGTOOL_ check $1 2> /dev/null ; then
757 # Make sure the registry key exists
758 create_registry_key "$1"
760 $REGTOOL -s set $1/ \"$3\"
761 $REGTOOL add $1/command
762 $REGTOOL -e set $1/command/ \"$4\"
763 else
764 echo $0 Warning: Not overriding existing entry
765 echo
766 echo Entry for $2 already exists in the Registry Drive Key
767 echo Use -f to override existing key.
768 echo
772 # Create uninstall entries
773 # Arguments:
774 # $1 - Registry key to create
775 # $2 - Shell being installed
776 # Uses:
777 # FORCE
778 # CPH_DESC
779 # ASH_EXE
780 # UINST_ARG
781 create_uninstall_item()
783 # Add uninstall registry entry
784 if [ $FORCE = t ] || ! $REGTOOL_ check $1 2> /dev/null ; then
785 # Actually, should create an .inf so windows can get rid of the menu entries
786 # even after the cygwin directory is wiped :(
787 if $REGTOOL add $1 ; then
788 $REGTOOL -s set $1/DisplayName \"$CPH_DESC\"
789 $REGTOOL -s set $1/UnInstallString \"$ASH_EXE -c \\\"PATH=/bin /bin/chere $UINST_ARG -u -s $2\\\"\"
790 else
791 echo $0 Error: Couldn\'t modify HKLM hive.
792 echo Control Panel uninstall will not be available.
794 else
795 echo $0 Warning: Not overriding existing entry
796 echo
797 echo Entry for $2 already exists in the Registry uninstall section
798 echo Use -f to override existing key.
799 echo
803 # Install named term and shell combination
804 # Arguments:
805 # $1 - Terminal to install
806 # $2 - Shell to install
807 # Uses:
808 # FORCE
809 # DO_WIN_UINST
810 # DRIVE_KEY
811 # DIR_KEY
812 # UINST_KEY
813 # ACCEL
814 # START_CMD
815 # SHELL_CMD
816 # PFX
817 install()
819 local TERM_EXE SHELL_EXE SHELL_CMD SHELL_BG_CMD START_CMD ACCEL CPH_DESC UINST_ARG
820 setup_for_term $1
821 setup_for_shell $2
823 # Check TERM and SHELL are present
824 if [ ! -x "$TERM_EXE" ] && [ "$1" != cmd ]; then
825 if [ $FORCE = t ]; then
826 echo $0 Warning: $TERM_EXE not found
827 else
828 echo $0 Error: $TERM_EXE not found
829 echo
830 echo $TERM_EXE is where I expect to find your $1
831 echo Use -f to install anyway.
832 exit
835 if [ ! -x "$SHELL_EXE" ] && [ "$2" != cmd ]; then
836 if [ $FORCE = t ]; then
837 echo $0 Warning: $SHELL_EXE not found
838 else
839 echo $0 Error: $SHELL_EXE not found
840 echo
841 echo $SHELL_EXE is where I expect to find $2
842 echo Use -f to install anyway.
843 exit
847 build_start_cmd $1 $2 $METHOD
849 ####### Install ###########
850 install_context_menu $DRIVE_KEY/$PFX$2 $2 "$ACCEL" "$START_CMD $SHELL_CMD"
851 install_context_menu $DIR_KEY/$PFX$2 $2 "$ACCEL" "$START_CMD $SHELL_CMD"
853 # Background keys only work on Windows 7. Don't install on XP.
854 if [ $VER != "CYGWIN_NT-5.1" ] ; then
855 install_context_menu $DRIVE_BG_KEY/$PFX$2 $2 "$ACCEL" "$START_CMD $SHELL_BG_CMD"
856 install_context_menu $DIR_BG_KEY/$PFX$2 $2 "$ACCEL" "$START_CMD $SHELL_BG_CMD"
859 if [ $DO_WIN_UINST = t ]; then
860 create_uninstall_item $UINST_KEY/$PFX$2 $2
864 # Arguments
865 # $1 - shell
866 # Uses:
867 # DRIVE_KEYS
868 # DIR_KEYS
869 # UINST_KEY
870 # PFX
871 uninstall()
873 for drive in $DRIVE_KEYS ; do
874 # Check each key exists before attempting to remove it
875 if $REGTOOL_ check $drive/$PFX$1/command 2> /dev/null; then
876 if ! $REGTOOL remove $drive/$PFX$1/command ; then
877 echo $0 Error: Hive not writable.
878 echo $0: Aborting.
879 exit
883 if $REGTOOL_ check $drive/$PFX$1 2> /dev/null; then
884 $REGTOOL remove $drive/$PFX$1
886 done
888 for dir in $DIR_KEYS ; do
889 if $REGTOOL_ check $dir/$PFX$1/command 2> /dev/null; then
890 $REGTOOL remove $dir/$PFX$1/command
892 if $REGTOOL_ check $dir/$PFX$1 2> /dev/null; then
893 $REGTOOL remove $dir/$PFX$1
895 done
897 if $REGTOOL_ check $UINST_KEY/$PFX$1 2> /dev/null; then
898 $REGTOOL remove $UINST_KEY/$PFX$1
902 #########################################################################
903 # Start of commands #
904 #########################################################################
906 # Need to use eval to force correct quote evaluation
907 REGTOOL="eval regtool -w"
908 REGTOOL_="regtool -w"
910 KNOWN_TERMS="cmd rxvt mintty xterm urxvt"
911 KNOWN_SHELLS="ash bash cmd dash fish mksh pdksh posh tcsh zsh passwd"
913 ALL_USERS=unset
914 ACTION=nothing
915 FRESHEN=f
916 DO_WIN_UINST=t
917 FORCE=f
918 LIST=f
919 READ=f
920 METHOD=2
921 PRINT=f
922 DISP=:0
923 USER_TERM_OPTIONS=
924 USER_MENU_TEXT=
925 # Used to set an extra argument for Control Panel uninstall for current user
926 UINST_ARG=""
928 # Default terminal and shell if not specified
929 this_term=cmd
930 #this_shell=passwd
932 ####################### Parse command line #######################
933 while getopts iuxlracnmpf12hvt:s:d:o:e: ARG
935 case "$ARG" in
936 i ) ACTION=i;;
937 u ) ACTION=u;;
938 x ) FORCE=t;FRESHEN=t;;
939 l ) LIST=t;;
940 r ) READ=t;;
941 a ) ALL_USERS=t;;
942 c ) ALL_USERS=f;;
943 n ) DO_WIN_UINST=t;;
944 m ) DO_WIN_UINST=f;;
945 p ) REGTOOL="echo ${REGTOOL_}"; PRINT=t;;
946 f ) FORCE=t;;
947 1 ) METHOD=1;;
948 2 ) METHOD=2;;
949 t ) this_term=$OPTARG;;
950 s ) this_shell=$OPTARG;;
951 d ) DISP=$OPTARG;;
952 o ) USER_TERM_OPTIONS="$OPTARG";;
953 e ) USER_MENU_TEXT="$OPTARG";;
954 \? | h ) print_help; exit;;
955 v ) echo $0 version $VERSION; exit;;
956 esac
957 done
959 check_requirements
960 get_system_info
962 # if DISP set to env, make sure we set it to read from the environment
963 if [ $DISP = env ]; then
964 DISP="%DISPLAY%"
967 if [ $FRESHEN = t ]; then
969 # If the user has specified -e, abort since this is not right
970 if [ -n "$USER_MENU_TEXT" ]; then
971 echo "$0 error: You really don\'t want to freshen your existing entires,"
972 echo " and set all the context menus to the same string of text."
973 echo $0: Aborting.
974 exit
977 # Do current user first so that we don't bail
978 # if we don't have rights to HKCR
979 for user in f t; do
980 set_for_user i $user
982 INSTALLED=`list_cygwin_registry_keys $DIR_KEY`
983 echo Updating shells $INSTALLED
984 for this_shell in $INSTALLED; do
985 this_term=`find_term_of_installed_shell $this_shell`
986 install $this_term $this_shell
987 done
988 done
990 elif [ $ACTION = i ]; then
992 set_for_user $ACTION $ALL_USERS
994 # If no shell specified at this stage,
995 # grab one from /etc/passwd if it is present
996 if [ ! $this_shell ]; then
997 this_shell=`get_shell_from_passwd`
998 if [ -n "$this_shell" ] ; then
999 echo Shell defaulting to $this_shell defined for $ID_USER
1000 else
1001 echo $0 Error: No shell specified, and passwd entry could not be read
1002 echo
1003 echo Can\'t guess what shell you want.
1004 echo Use -s to specify the shell.
1005 exit
1009 install $this_term $this_shell
1011 elif [ $ACTION = u ]; then
1013 set_for_user $ACTION $ALL_USERS
1015 if [ -z "$this_shell" ]; then
1016 # No shell specified, remove all
1017 UINST_SHELLS=$KNOWN_SHELLS
1018 else
1019 UINST_SHELLS=$this_shell
1022 # Uninstall each shell
1023 for ushell in $UINST_SHELLS ; do
1024 uninstall $ushell
1025 done
1027 # Remove keys after we've cleared out our entries
1028 for key in $DRIVE_KEYS $DIR_KEYS ; do
1029 remove_registry_key $key
1030 done
1034 if [ $READ = t ]; then
1035 # Print some useful information
1036 echo OS is $VER
1037 echo chere version $VERSION
1038 if [ -n "$RUN_EXE" ]; then
1039 echo run.exe is available at $RUN_EXE
1041 echo
1042 read_chere_registry_keys
1045 # If requested, list what is currently installed
1046 # Rely on the DIR key rather than UINST key,
1047 # since user may pass -m, or HKLM may not be writable
1048 if [ $LIST = t ]; then
1049 echo Currently installed Cygwin Here shells \(all users\):
1050 list_cygwin_registry_keys $DIR_KEY_CR
1051 echo
1052 echo Currently installed Cygwin Here shells \(current user\):
1053 list_cygwin_registry_keys $DIR_KEY_CU
1056 if [ $FRESHEN = f ] && [ $ACTION = nothing ] && [ $LIST = f ] && [ $READ = f ]; then
1057 echo $0: No action taken
1058 print_help