chere 1.0-1
[chere.git] / src / chere
blob42975c85215b0c9a58719a5f7de55ba13c8dd4f4
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 # Sept 2007
19 VERSION=1.0
20 # Option to add to the terminal startup command.
21 # Option to specify context menu text.
22 # Together these options allow you to add a context menu to start
23 # named terminals (that have different properties, configured in
24 # .Xdefaults).
25 # Revert to using bash getopts to handle spaces in new options arguments.
26 #VERSION=0.8
27 # Set path and DISPLAY for xterm
28 # Thanks to Lewis Hyatt for pointing this out and Paul Mallas for
29 # identifying the -display option.
30 # Fix find_term_of_installed_shell so it copes better if the command
31 # is not in the precise format we expect.
32 #VERSION=0.7
33 # Abort registry key removal as soon as we notice a non-empty key
34 # Print help immediately if no action
35 # Make context menu text clearer
36 # Thanks to Brian Mathis
37 #VERSION=0.6-1
38 # Correct bad function call to get_shell_from_passwd
39 # Thanks to Dave Griffin
40 #VERSION=0.6
41 # Restructure to use shell functions
42 # Add version option
43 # Add -x option to update current entries
44 # Enter correct directory when using the RH pane
45 # Thanks to Nils Jeppe
46 #VERSION=0.5
47 # Add back -a and -c options to set options in HKCU
48 # Make sure the appropriate entries are uninstalled when run.
49 # (Obey -a and -c options)
50 # Note a user can't uninstall for another user
51 # Remove reference to -x that sneaked into help
52 # Rationalize help as chere now has a man page
53 # sed now required to parse XX_KEYS and ensure they exist
54 #VERSION=0.4
55 # Add r to synopsis
56 # Remove redundant TERM_CMDs and CYG_DIR
57 # Use run.exe if I can find it
58 # Add -1 and -2 options to determine how to start the shell. 2 is default
59 # -2 fixes reported issues with network paths and tcsh/ash login shells
60 # Thanks to Igor Petchanksi, Andrew Grimm, Munehiro (haro) Matsuda
61 # -2 untested on XP/NT/95/98/ME
62 #VERSION=0.3
63 # Use forward slashes for command to fix XP problems (CGF)
64 # Correct quoting (CGF)
65 # Add -r option to read registry entries to stdout to help debugging
66 #VERSION=0.2
67 # Use consistent registry key based on shell id
68 # Fixup windows version check
69 # Use correct cmd/command quoting
70 # Add list option, install is no longer default
71 # Check regtool/sed is present
72 # Add xterm -e arg
73 # Check the term/shell is present before installing (except cmd)
74 # Add information on window title and login shells
75 # Set pdksh, tcsh, zsh to start login shells
76 # Case statements ash compatible
77 # Look in passwd for shell if not specified
78 # Mental runtime check of passwd added. Use at own risk
79 # Changed to use getopt and removed [[ ]] tests. Ash compatible.
80 # Updated shebang
81 #VERSION=0.1
82 # Initial implementation.
83 # Bash required.
84 # Possible quoting problems.
85 # Windows uninstall only posible if script present
88 #########################################################################
89 # Define functions (for modularity and readability) #
90 #########################################################################
92 # Prints usage information
93 print_help()
95 cat <<-EOF
96 $0 version $VERSION
98 Usage:
99 $0 -<iuxlrhv> [-lracnmpf12] [-t <term>] [-s <shell>]
100 [-d <display> ] [-o <options>] [-e <menutext>]
102 Adds the stated terminal/shell combination to the folder context menu
103 This allows you to right click a folder in Windows Explorer and open
104 a Cygwin shell in that folder.
106 Options:
107 i - Install
108 u - Uninstall
109 x - Freshen eXisting entries
110 l - List currently installed chere items
111 r - Read all chere registry entries to stdout
112 a - All users
113 c - Current user only
114 n - Be Nice and provide Control Panel uninstall option (Default)
115 m - Minimal, no Control Panel uninstall
116 p - Print regtool commands to stdout rather than running them
117 f - Force write (overwrite existing, ignore missing files)
118 1 - Start using registry one-liners. This doesn't work with ash,
119 tcsh or network shares.
120 2 - Start via bash script. Relies on windows to change directory,
121 and login scripts avoiding doing a cd $HOME
122 h - Help
123 v - Version
125 t <term> - Use terminal term. Supported terminals are:
126 $KNOWN_TERMS
128 s <shell> - Use the named shell. Supported shells are:
129 $KNOWN_SHELLS
131 d <display> - DISPLAY to use (xterm only). Defaults to :0.
132 Set to env to use the runtime environment variable.
134 o <options> - Add <options> to the terminal startup command.
135 If more than one option is specified, they should all be
136 contained within a single set of quotes.
138 e <menutext> - Use <menutext> as the context menu text.
140 See the man page for more detail.
142 # Handle unclosed quote for syntax highlighting '
145 # Function to verify all required utilies are present
146 # Notes:
147 # Exits if any required utilites are missing
148 check_requirements()
150 # Quick check of common utilities (from sh-utils, cygwin, textutils packages)
151 if [ ! -x /bin/uname ] || [ ! -x /bin/cygpath ] || [ ! -x /bin/id ] || [ ! -x /bin/wc ] || [ ! -x /bin/sed ] ; then
152 echo $0 Error: uname / id / cygpath / wc / sed not found
153 echo
154 echo These tools are required for correct operation.
155 echo $0: Aborting
156 exit
159 # Check we have regtool (from cygwin package)
160 if [ ! -x /bin/regtool ]; then
161 echo $0 Error: /bin/regtool not found
162 echo
163 echo You need regtool installed for this script to work.
164 echo $0: Aborting.
165 exit
170 # Get information about the current system
171 # Sets:
172 # VER - system version
173 # ID_USER - username
174 # RUN_EXE - windows path to run.exe if present
175 # ASH_EXE - windows path to ash if present
176 # BASH_EXE - windows path to bash if present
177 # DIR_KEY_CU - Registry key for directory context menu for current user
178 # DRIVE_KEY_CU - Registry key for drive context menu for current user
179 # DIR_KEY_CR - Registry key for directory context menu for all users
180 # DRIVE_KEY_CR - Registry key for drive context menu for all users
181 # UINST_KEY - Registry key for uninstall information
182 get_system_info()
184 # Check windows version and cygwin install directory
185 VER=`uname -s`
186 ID_USER=`id -nu`
187 RUN_EXE=""
188 ASH_EXE=`cygpath -w /bin/sh`
189 BASH_EXE=`cygpath -w /bin/bash`
191 if [ -x /bin/which ]; then
192 # Enable prepending of run.exe if we can find it.
193 # I'm assuming run has been placed in the path.
195 # We did this because run.exe was packaged in X-startup-scripts.
196 # It is now in its own package and part of base.
197 # However, continue to check for it in this way.
199 RUN_EXE=`which run.exe 2>/dev/null`
200 if [ -n "$RUN_EXE" ]; then
201 # Convert to windows path
202 RUN_EXE=`cygpath -w "$RUN_EXE"`
206 # Identify the registry keys for each OS and desired set of users
207 # Same for all?
208 # Note that the entry /HKCU/Software/Classes may not exist, and may need
209 # to be created for the user.
210 DIR_KEY_CR=/HKCR/Directory/Shell
211 DRIVE_KEY_CR=/HKCR/Drive/Shell
212 DIR_KEY_CU=/HKCU/Software/Classes/Directory/Shell
213 DRIVE_KEY_CU=/HKCU/Software/Classes/Drive/Shell
214 UINST_KEY=/HKLM/Software/Microsoft/Windows/CurrentVersion/Uninstall
217 # Selects the registry entries to use based on action and user.
218 # Arguments:
219 # $1 - Action. If install output keys to install for. Otherwise keys to remove
220 # $2 - If TRUE (not f), set for all users.
221 # Otherwise, set for current user.
222 # Sets:
223 # DIR_KEY - Registry key for directory context menu
224 # DRIVE_KEY - Registry key for drive context menu
225 # DIR_KEYS - Registry keys to be removed (directory)
226 # DRIVE_KEYS - Registry keys to be removed (drive)
227 # UINST_ARG - Argument to pass to chere on uninstall
228 # Refers to:
229 # DIR_KEY_CU - Registry key for directory context menu for current user
230 # DRIVE_KEY_CU - Registry key for drive context menu for current user
231 # DIR_KEY_CR - Registry key for directory context menu for all users
232 # DRIVE_KEY_CR - Registry key for drive context menu for all users
233 set_for_user()
235 if [ $1 = i ]; then
236 # Set for install
237 if [ $2 = f ]; then
238 DIR_KEY=$DIR_KEY_CU
239 DRIVE_KEY=$DRIVE_KEY_CU
240 UINST_ARG="-c"
241 else
242 # all users is the default
243 DIR_KEY=$DIR_KEY_CR
244 DRIVE_KEY=$DRIVE_KEY_CR
246 else
247 # Set for uninstall
248 if [ $2 = t ]; then
249 # Don't remove HKCU entries
250 DRIVE_KEYS=$DRIVE_KEY_CR
251 DIR_KEYS=$DIR_KEY_CR
252 elif [ $2 = f ]; then
253 # Don't remove HKCR entries
254 DRIVE_KEYS=$DRIVE_KEY_CU
255 DIR_KEYS=$DIR_KEY_CU
256 else
257 # Else remove both HKCR and HKCU entries
258 DRIVE_KEYS="$DRIVE_KEY_CR $DRIVE_KEY_CU"
259 DIR_KEYS="$DIR_KEY_CR $DIR_KEY_CU"
264 # Sets this_shell, based on current users passwd entry
265 # Sets:
266 # this_shell - shell to install
267 # Uses:
268 # ID_USER - current user
269 # Notes:
270 # Exits if /etc/passwd not found
271 get_shell_from_passwd()
273 if [ -f /etc/passwd ]; then
274 this_shell=`sed -n "s?$ID_USER:.*:/bin/\(.*\)?\1?gp" /etc/passwd`
275 echo Shell defaulting to $this_shell defined for $ID_USER
276 else
277 echo $0 Error: No shell specified, and /etc/passwd not present
278 echo
279 echo Can\'t guess what shell you want.
280 echo Use -s to specify the shell.
281 exit
285 # Identifies the terminal installed for the named shell
286 # Parameters:
287 # $1 - shell
288 # Uses:
289 # DIR_KEY - Registry base to find shell entry
290 find_term_of_installed_shell()
292 # local KEY_VALUE TERM_REGEXP
294 # use sed to strip everything except known terminals
295 # construct the regexp of known terminals from KNOWN_TERMS
296 # add command as well to pick up on 9x
297 TERM_REGEXP=`echo $KNOWN_TERMS command | sed 's/ \+/\\\\|/g'`
298 KEY_VALUE=`$REGTOOL_ get $DIR_KEY/cygwin_$1/command/ | sed "s/.*\($TERM_REGEXP\).*/\1/g"`
300 if [ "$KEY_VALUE" = "command" ]; then
301 KEY_VALUE=cmd
303 echo $KEY_VALUE
304 unset KEY_VALUE
305 unset TERM_REGEXP
308 # Setup to install for a particular terminal
309 # Arguments:
310 # $1 - term to setup for
311 # Sets:
312 # TERM_EXE - path to terminals executable
313 # TERM_ARGS - arguments to pass to the terminal
314 # RUN_ARGS - arguments to pass to run.exe
315 # Uses:
316 # VER - OS version
317 # KNOWN_TERMS - list of known terminals
318 # DISP - display to use for xterm
319 # USER_TERM_OPTIONS - users custom options for terminal
320 # Notes:
321 # Exits if term is not recognised
322 setup_for_term()
324 #################### Define terminals ########################
325 # For each terminal, indicate the executable in TERM_EXE.
326 # Unless it is cmd, it is assumed that -e passes the startup
327 # command
328 TERM_ARGS=""
329 RUN_ARGS=""
330 case $1 in
331 cmd )
332 case $VER in
333 CYGWIN_NT* )
334 TERM_EXE=cmd.exe;;
336 TERM_EXE=command.com;;
337 esac
338 TERM_ARGS="$USER_TERM_OPTIONS";;
339 rxvt )
340 TERM_EXE="/bin/rxvt.exe"
341 TERM_ARGS="$USER_TERM_OPTIONS";;
342 xterm )
343 TERM_EXE="/bin/xterm.exe"
344 TERM_ARGS="-display $DISP $USER_TERM_OPTIONS"
345 RUN_ARGS="-p /usr/X11R6/bin";;
347 echo $0 Error: Unknown terminal $this_term
348 echo
349 echo Supported terminals:
350 echo $KNOWN_TERMS
351 echo
352 echo Use -h for help
353 exit;;
354 esac
357 # Setup to install a particular shell.
358 # Arguments:
359 # $1 - shell to install
360 # Sets:
361 # SHELL_EXE - path to shell executable
362 # SHELL_CMD - argument to pass to shell executable (Method 1 only)
363 # ACCEL - context menu text
364 # CPH_DESC - description for uninstall
365 # Uses:
366 # VER - OS version
367 # FORCE - set to t to force installation of passwd in its absence
368 # KNOWN_SHELLS - list of known shells
369 # USER_MENU_TEXT - User specified menu text
371 # Notes:
372 # If shell is passwd, checks for the presence of /etc/passwd
373 # Exits if shell is passwd, /etc/passwd not found and FORCE is not t.
374 # Exits if shell is not recognised
375 setup_for_shell()
377 #################### Define shells #############################
378 # For each shell, specify:
379 # the location of the executable to be checked on install
380 # the arguments that should be used to start it in the directory %1, and keep it open.
381 # the accelerator to be displayed on the menu
382 # the description text to be displayed in control panel uninstall window
383 case $1 in
384 bash )
385 SHELL_EXE="/bin/bash.exe"
386 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
387 ACCEL="&Bash Prompt Here"
388 CPH_DESC="Cygwin Bash Prompt Here";;
389 ash )
390 # TODO How to make this a login shell? Is -l undocumented?
391 SHELL_EXE="/bin/sh.exe"
392 SHELL_CMD="-c \\\"cd '%L'; exec $SHELL_EXE\\\"";
393 ACCEL="&Ash Prompt Here"
394 CPH_DESC="Cygwin Ash Prompt Here";;
395 pdksh )
396 SHELL_EXE="/bin/pdksh.exe"
397 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
398 ACCEL="&Pdksh Prompt Here"
399 CPH_DESC="Cygwin Pdksh Prompt Here";;
400 tcsh )
401 # Apparently -l only applies if it is the only argument
402 # so this may not work
403 SHELL_EXE="/bin/tcsh.exe"
404 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
405 ACCEL="&Tcsh Prompt Here"
406 CPH_DESC="Cygwin Tcsh Prompt Here";;
407 zsh )
408 SHELL_EXE="/bin/zsh.exe"
409 SHELL_CMD="-l -c \\\"cd '%L'; exec $SHELL_EXE\\\""
410 ACCEL="&Zsh Prompt Here"
411 CPH_DESC="Cygwin Zsh Prompt Here";;
412 cmd )
413 case $VER in
414 CYGWIN_NT* )
415 SHELL_EXE=cmd.exe
416 SHELL_CMD="/k cd %L";;
418 SHELL_EXE=command.com
419 SHELL_CMD="/k cd \\\"%1\\\"";;
420 esac
421 ACCEL="&Command Prompt Here"
422 CPH_DESC="Command Prompt Here (cygwin)";;
423 passwd )
424 # Experimental
425 SHELL_EXE="/bin/sh"
426 # Quoting nightmare. Step through it all
427 # c:\cygwin\bin\sh -c "scmd=`sed -n \"s?\`id -un\`:.*:\\\(.*\\\)?\\\1?gp\" /etc/passwd`; $scmd -l -c \"cd 'c:/program files'; exec $scmd\""
428 # works from the command line
429 # In registry it needs to read the same:
430 # c:\cygwin\bin\sh -c "scmd=`sed -n \"s?\`id -un\`:.*:\\\(.*\\\)?\\\1?gp\" /etc/passwd`; $scmd -l -c \"cd '%1'; exec $scmd\""
431 # When passed to regtool, need to requote for the shell:
432 # "c:\cygwin\bin\sh -c \"scmd=\`sed -n \\\"s?\\\`id -un\\\`:.*:\\\\\\(.*\\\\\\)?\\\\\\1?gp\\\" /etc/passwd\`; \$scmd -l -c \\\"cd '%1'; exec \$scmd\\\"\""
433 # When evaluated into a variable, need another level of quoting:
434 # "c:\cygwin\bin\sh -c \\\"scmd=\\\`sed -n \\\\\\\"s?\\\\\\\`id -un\\\\\\\`:.*:\\\\\\\\\\\\(.*\\\\\\\\\\\\)?\\\\\\\\\\\\1?gp\\\\\\\" /etc/passwd\\\`; \\\$scmd -l -c \\\\\\\"cd '%1'; exec \\\$scmd\\\\\\\"\\\""
435 # Ouch. If you think it can be quoted better, let me know.
436 SHELL_CMD="-c \\\"scmd=\\\`sed -n \\\\\\\"s?\\\\\\\`id -un\\\\\\\`:.*:\\\\\\\\\\\\(.*\\\\\\\\\\\\)?\\\\\\\\\\\\1?gp\\\\\\\" /etc/passwd\\\`; \\\$scmd -l -c \\\\\\\"cd '%L'; exec \\\$scmd\\\\\\\"\\\""
437 ACCEL="Shell Prompt &Here"
438 CPH_DESC="Cygwin Prompt Here"
440 # Extra check before installing passwd
441 if [ ! -f /etc/passwd ]; then
442 if [ $FORCE = t ]; then
443 echo $0 Warning: /etc/passwd not found
444 echo
445 echo This file is required for the runtime context menu item to work.
446 echo Run mkpasswd
447 else
448 echo $0 Error: /etc/passwd not found
449 echo
450 echo This file is required for the runtime context menu item to work.
451 echo Run mkpasswd to initialise the file.
452 echo Use -f to install anyway.
453 exit
455 fi;;
457 echo $0 Error: Unknown shell $this_shell
458 echo
459 echo Supported shells:
460 echo $KNOWN_SHELLS
461 echo
462 echo Use -h for help
463 exit;;
464 esac
466 # Override standard accelerator if specified
467 if [ -n "$USER_MENU_TEXT" ] ; then
468 ACCEL="$USER_MENU_TEXT"
472 # Builds the command to execute when the context menu item is selected
473 # Arguments:
474 # $1 - Terminal to use
475 # $2 - Shell to install
476 # $3 - Method used to invoke term/shell combo
477 # Sets:
478 # START_CMD - command to execute
479 # SHELL_EXE - modified if this_shell is passwd and using method 2
480 # SHELL_CMD - cleared if using method 2
481 # Uses:
482 # RUN_EXE - location of run.exe if present
483 # RUN_ARGS - argument to pass to run.exe
484 # TERM_EXE - location of terminal executable
485 # TERM_ARGS - arguments to pass to reminal
486 # SHELL_EXE - location of shell executable
487 build_start_cmd()
489 # local TERM_WIN_EXE XHERE
490 # TERM_EXE needs to be called by a windows path, even from run.exe
491 TERM_WIN_EXE=`cygpath -w "$TERM_EXE"`
492 if [ $3 = 1 ]; then
493 # METHOD 1 - invoke term and shell directly from the registry
494 if [ $1 != cmd ]; then
495 if [ -n "$RUN_EXE" ]; then
496 START_CMD="$RUN_EXE $RUN_ARGS $TERM_WIN_EXE $TERM_ARGS -e $SHELL_EXE"
497 else
498 START_CMD="$TERM_WIN_EXE $TERM_ARGS -e $SHELL_EXE"
500 elif [ $2 != cmd ]; then
501 # With cmd (term), the shell executable needs to be converted
502 # to a windows path
503 # With cmd, we ignore TERM_CMD.
504 START_CMD=`cygpath -w "$SHELL_EXE"`
505 else
506 # term and shell are cmd
507 START_CMD=$SHELL_EXE
509 else
510 # METHOD 2 - invoke xhere from the registry
511 XHERE="/bin/xhere"
512 if [ $2 = cmd ]; then
513 # Clear XHERE for when running command from rxvt/xterm
514 XHERE="";
515 elif [ $2 = passwd ]; then
516 # Have XHERE do the call rather than bung it in the registry
517 SHELL_EXE="/etc/passwd"
520 if [ $1 != cmd ]; then
521 if [ -n "$RUN_EXE" ]; then
522 START_CMD="$RUN_EXE $RUN_ARGS $TERM_WIN_EXE $TERM_ARGS -e $XHERE $SHELL_EXE"
523 else
524 START_CMD="$TERM_WIN_EXE $TERM_ARGS -e $XHERE $SHELL_EXE"
526 if [ $2 != cmd ]; then
527 SHELL_CMD="\\\"%L\\\""
529 elif [ $2 != cmd ]; then
530 START_CMD="`cygpath -w \"$BASH_EXE\"`"
531 SHELL_CMD="-c \\\"$XHERE $SHELL_EXE '%L'\\\""
532 else
533 # The command shell won't cd anywhere anyway
534 START_CMD=$SHELL_EXE
536 unset XHERE
538 unset TERM_WIN_EXE
541 # Create full path to registry key
542 # Arguments:
543 # $1 - Registry key to create
544 # Notes:
545 # Exits if key cannot be created
546 create_registry_key()
548 # local KEY_ELEMENTS CUR_KEY
549 KEY_ELEMENTS=`echo $1 | sed "s?/? ?g"`
550 CUR_KEY=
551 for elem in $KEY_ELEMENTS; do
552 CUR_KEY=$CUR_KEY/$elem
553 if ! $REGTOOL_ check $CUR_KEY 2>/dev/null ; then
554 # elem not present, so add it
555 if ! $REGTOOL add $CUR_KEY ; then
556 echo $0 Error: Hive not writable
557 echo $0: Aborting.
558 exit
561 done
562 unset KEY_ELEMENTS CUR_KEY
565 # Removes a key and any empty parents
566 # $1 - key to remove
567 remove_registry_key()
569 # local CUR_KEY ENTRIES
570 CUR_KEY=$1
571 if $REGTOOL_ check $CUR_KEY 2> /dev/null; then
572 while [ -n "$CUR_KEY" ]; do
573 ENTRIES=`$REGTOOL_ list $CUR_KEY | wc -l`
574 if [ $ENTRIES = "0" ] || ( [ $ENTRIES = "1" ] && [ $PRINT = t ] ); then
575 # Remove empty key
576 $REGTOOL remove $CUR_KEY
577 CUR_KEY=`echo $CUR_KEY | sed "s?/[^/]*\\$??g"`
578 else
579 # Abort
580 CUR_KEY=
582 done
584 unset CUR_KEY ENTRIES
587 # Print registry keys and values that chere knows about
588 # Uses:
589 # KNOWN_SHELLS - list of known shells
590 # DIR_KEY_CU - Registry key for directory context menu for current user
591 # DRIVE_KEY_CU - Registry key for drive context menu for current user
592 # DIR_KEY_CR - Registry key for directory context menu for all users
593 # DRIVE_KEY_CR - Registry key for drive context menu for all users
594 # UINST_KEY - Registry key for uninstall information
595 read_chere_registry_keys()
597 # local builtin is not available for sh (but is for ash and bash)
598 # local FOR_WHO=""
599 for shell in $KNOWN_SHELLS; do
600 echo --- $shell keys ---
601 #### Directory entries ####
602 FOR_WHO="(all users)"
603 for dir in $DIR_KEY_CR $DIR_KEY_CU ; do
604 if $REGTOOL_ check $dir/cygwin_$shell 2> /dev/null; then
605 echo Directory menu item $FOR_WHO
606 $REGTOOL get $dir/cygwin_$shell/
607 echo
609 if $REGTOOL_ check $dir/cygwin_$shell/command 2> /dev/null; then
610 echo Directory command $FOR_WHO
611 $REGTOOL get $dir/cygwin_$shell/command/
612 echo
614 FOR_WHO="(current user)"
615 done
616 #### Drive entries ####
617 FOR_WHO="(all users)"
618 for drive in $DRIVE_KEY_CR $DRIVE_KEY_CU ; do
619 if $REGTOOL_ check $drive/cygwin_$shell 2> /dev/null; then
620 echo Drive menu item $FOR_WHO
621 $REGTOOL get $drive/cygwin_$shell/
622 echo
624 if $REGTOOL_ check $drive/cygwin_$shell/command 2> /dev/null; then
625 echo Drive command $FOR_WHO
626 $REGTOOL get $drive/cygwin_$shell/command/
627 echo
629 FOR_WHO="(current user)"
630 done
631 #### UnInstall entries ####
632 if $REGTOOL_ check $UINST_KEY/cygwin_$shell 2> /dev/null; then
633 echo Uninstall description
634 $REGTOOL get $UINST_KEY/cygwin_$shell/DisplayName
635 echo
636 echo Uninstall command
637 $REGTOOL get $UINST_KEY/cygwin_$shell/UnInstallString
638 echo
640 echo
641 done
642 # Since local is not available...
643 unset FOR_WHO
646 # Lists all cygwin items in given registry node to stdout
647 # Parameters:
648 # $1 - Node to search
649 list_cygwin_registry_keys()
651 $REGTOOL_ list $1 2> /dev/null | sed -n 's/cygwin_\(.*\)/\1/gp'
654 # Install keys under $1 for shell $2
655 # Arguments:
656 # $1 - Registry key to create
657 # $2 - Shell being installed
658 # Uses:
659 # FORCE
660 # ACCEL
661 # START_CMD
662 # SHELL_CMD
663 install_context_menu()
665 if [ $FORCE = t ] || ! $REGTOOL_ check $1 2> /dev/null ; then
666 # Make sure the registry key exists
667 create_registry_key "$1"
669 $REGTOOL -s set $1/ \"$ACCEL\"
670 $REGTOOL add $1/command
671 $REGTOOL -e set $1/command/ \"$START_CMD $SHELL_CMD\"
672 else
673 echo $0 Warning: Not overriding existing entry
674 echo
675 echo Entry for $2 already exists in the Registry Drive Key
676 echo Use -f to override existing key.
677 echo
681 # Create uninstall entries
682 # Arguments:
683 # $1 - Registry key to create
684 # $2 - Shell being installed
685 # Uses:
686 # FORCE
687 # CPH_DESC
688 # ASH_EXE
689 # UINST_ARG
690 create_uninstall_item()
692 # Add uninstall registry entry
693 if [ $FORCE = t ] || ! $REGTOOL_ check $1 2> /dev/null ; then
694 # Actually, should create an .inf so windows can get rid of the menu entries
695 # even after the cygwin directory is wiped :(
696 if $REGTOOL add $1 ; then
697 $REGTOOL -s set $1/DisplayName \"$CPH_DESC\"
698 $REGTOOL -s set $1/UnInstallString \"$ASH_EXE -c \\\"/bin/chere $UINST_ARG -u -s $2\\\"\"
699 else
700 echo $0 Error: Couldn\'t modify HKLM hive.
701 echo Control Panel uninstall will not be available.
703 else
704 echo $0 Warning: Not overriding existing entry
705 echo
706 echo Entry for $2 already exists in the Registry uninstall section
707 echo Use -f to override existing key.
708 echo
712 # Install named term and shell combination
713 # Arguments:
714 # $1 - Terminal to install
715 # $2 - Shell to install
716 # Uses:
717 # FORCE
718 # DO_WIN_UINST
719 # DRIVE_KEY
720 # DIR_KEY
721 # UINST_KEY
722 install()
724 # local TERM_EXE SHELL_EXE SHELL_CMD START_CMD ACCEL CPH_DESC UINST_ARG
725 setup_for_term $1
726 setup_for_shell $2
728 # Check TERM and SHELL are present
729 if [ ! -x "$TERM_EXE" ] && [ "$1" != cmd ]; then
730 if [ $FORCE = t ]; then
731 echo $0 Warning: $TERM_EXE not found
732 else
733 echo $0 Error: $TERM_EXE not found
734 echo
735 echo $TERM_EXE is where I expect to find your $1
736 echo Use -f to install anyway.
737 exit
740 if [ ! -x "$SHELL_EXE" ] && [ "$2" != cmd ]; then
741 if [ $FORCE = t ]; then
742 echo $0 Warning: $SHELL_EXE not found
743 else
744 echo $0 Error: $SHELL_EXE not found
745 echo
746 echo $SHELL_EXE is where I expect to find $2
747 echo Use -f to install anyway.
748 exit
752 build_start_cmd $1 $2 $METHOD
754 ####### Install ###########
755 install_context_menu $DRIVE_KEY/cygwin_$2 $2
756 install_context_menu $DIR_KEY/cygwin_$2 $2
758 if [ $DO_WIN_UINST = t ]; then
759 create_uninstall_item $UINST_KEY/cygwin_$2 $2
762 unset TERM_EXE SHELL_EXE SHELL_CMD START_CMD ACCEL CPH_DESC UINST_ARG
765 # Arguments
766 # $1 - shell
767 # Uses:
768 # DRIVE_KEYS
769 # DIR_KEYS
770 # UINST_KEY
771 uninstall()
773 for drive in $DRIVE_KEYS ; do
774 # Check each key exists before attempting to remove it
775 if $REGTOOL_ check $drive/cygwin_$1/command 2> /dev/null; then
776 if ! $REGTOOL remove $drive/cygwin_$1/command ; then
777 echo $0 Error: Hive not writable.
778 echo $0: Aborting.
779 exit
783 if $REGTOOL_ check $drive/cygwin_$1 2> /dev/null; then
784 $REGTOOL remove $drive/cygwin_$1
786 done
788 for dir in $DIR_KEYS ; do
789 if $REGTOOL_ check $dir/cygwin_$1/command 2> /dev/null; then
790 $REGTOOL remove $dir/cygwin_$1/command
792 if $REGTOOL_ check $dir/cygwin_$1 2> /dev/null; then
793 $REGTOOL remove $dir/cygwin_$1
795 done
797 if $REGTOOL_ check $UINST_KEY/cygwin_$1 2> /dev/null; then
798 $REGTOOL remove $UINST_KEY/cygwin_$1
802 #########################################################################
803 # Start of commands #
804 #########################################################################
806 # Need to use eval to force correct quote evaluation
807 REGTOOL="eval regtool"
808 REGTOOL_=regtool
810 KNOWN_TERMS="cmd rxvt xterm"
811 KNOWN_SHELLS="ash bash cmd pdksh tcsh zsh passwd"
813 ALL_USERS=unset
814 ACTION=nothing
815 FRESHEN=f
816 DO_WIN_UINST=t
817 FORCE=f
818 LIST=f
819 READ=f
820 METHOD=2
821 PRINT=f
822 DISP=:0
823 USER_TERM_OPTIONS=
824 USER_MENU_TEXT=
825 # Used to set an extra argument for Control Panel uninstall for current user
826 UINST_ARG=""
828 # Default terminal and shell if not specified
829 this_term=cmd
830 #this_shell=passwd
832 ####################### Parse command line #######################
833 while getopts iuxlracnmpf12hvt:s:d:o:e: ARG
835 case "$ARG" in
836 i ) ACTION=i;;
837 u ) ACTION=u;;
838 x ) FORCE=t;FRESHEN=t;;
839 l ) LIST=t;;
840 r ) READ=t;;
841 a ) ALL_USERS=t;;
842 c ) ALL_USERS=f;;
843 n ) DO_WIN_UINST=t;;
844 m ) DO_WIN_UINST=f;;
845 p ) REGTOOL="echo regtool"; PRINT=t;;
846 f ) FORCE=t;;
847 1 ) METHOD=1;;
848 2 ) METHOD=2;;
849 t ) this_term=$OPTARG;;
850 s ) this_shell=$OPTARG;;
851 d ) DISP=$OPTARG;;
852 o ) USER_TERM_OPTIONS="$OPTARG";;
853 e ) USER_MENU_TEXT="$OPTARG";;
854 \? | h ) print_help; exit;;
855 v ) echo $0 version $VERSION; exit;;
856 esac
857 done
859 check_requirements
860 get_system_info
862 # if DISP set to env, make sure we set it to read from the environment
863 if [ $DISP = env ]; then
864 DISP="%DISPLAY%"
867 if [ $FRESHEN = t ]; then
869 # If the user has specified -e, abort since this is not right
870 if [ -n "$USER_MENU_TEXT" ]; then
871 echo "$0 error: You really don\'t want to freshen your existing entires,"
872 echo " and set all the context menus to the same string of text."
873 echo $0: Aborting.
874 exit
877 # Do current user first so that we don't bail
878 # if we don't have rights to HKCR
879 for user in f t; do
880 set_for_user i $user
882 INSTALLED=`list_cygwin_registry_keys $DIR_KEY`
883 echo Updating shells $INSTALLED
884 for this_shell in $INSTALLED; do
885 this_term=`find_term_of_installed_shell $this_shell`
886 install $this_term $this_shell
887 done
888 done
890 elif [ $ACTION = i ]; then
892 set_for_user $ACTION $ALL_USERS
894 # If no shell specified at this stage,
895 # grab one from /etc/passwd if it is present
896 if [ ! $this_shell ]; then
897 get_shell_from_passwd
900 install $this_term $this_shell
902 elif [ $ACTION = u ]; then
904 set_for_user $ACTION $ALL_USERS
906 if [ -z "$this_shell" ]; then
907 # No shell specified, remove all
908 UINST_SHELLS=$KNOWN_SHELLS
909 else
910 UINST_SHELLS=$this_shell
913 # Uninstall each shell
914 for ushell in $UINST_SHELLS ; do
915 uninstall $ushell
916 done
918 # Remove keys after we've cleared out our entries
919 for key in $DRIVE_KEYS $DIR_KEYS ; do
920 remove_registry_key $key
921 done
925 if [ $READ = t ]; then
926 # Print some useful information
927 echo OS is $VER
928 echo chere version $VERSION
929 if [ -n "$RUN_EXE" ]; then
930 echo run.exe is available at $RUN_EXE
932 echo
933 read_chere_registry_keys
936 # If requested, list what is currently installed
937 # Rely on the DIR key rather than UINST key,
938 # since user may pass -m, or HKLM may not be writable
939 if [ $LIST = t ]; then
940 echo Currently installed Cygwin Here shells \(all users\):
941 list_cygwin_registry_keys $DIR_KEY_CR
942 echo
943 echo Currently installed Cygwin Here shells \(current user\):
944 list_cygwin_registry_keys $DIR_KEY_CU
947 if [ $FRESHEN = f ] && [ $ACTION = nothing ] && [ $LIST = f ] && [ $READ = f ]; then
948 echo $0: No action taken
949 print_help