{"thread":{"id":"15978","subject":"[PATCH (GIT-GUI,MINGW) 3/3] Windows: Make OpenSSH properly detect tty detachment.","startedAt":"2008-10-20T16:02:17Z","lastAt":"2008-10-20T16:02:20Z","messageCount":4,"participants":["Alexander Gavrilov"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"93511","messageId":"1224518540-23782-1-git-send-email-angavrilov@gmail.com","threadId":"15978","inReplyTo":null,"subject":"[PATCH (GIT-GUI,MINGW) 0/3] Fix OpenSSH & Git-Gui integration in msysgit","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-10-20T16:02:17Z","receivedAt":"2008-10-20T16:02:17Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"\nIt is a well known problem on msysgit that when ssh is started\nfrom git-gui during a fetch, any situations where it normally\ndisplays a prompt to the user cause it to hang silently. It is\neven worse than the situation on Linux, where the prompts appear\non the terminal that started the GUI.\n\nThis combination of 3 patches aims to eliminate this problem. One\nof them changes a flag that is used to spawn the ssh executable,\nto make it recognize that it does not have a valid controlling\nconsole. The other two add features to git-gui that make ssh\nusage more convenient, including a simple implementation of an\nSSH_ASKPASS program.\n\nWhen the patches are applied, all SSH prompts in msysgit\nappear in a GUI dialog box in the middle of the screen.\nAdditionally, it is possible to view or create an OpenSSH\nkey pair directly from git-gui.\n\n\nNote: This was already posted to the msysgit list. The only differences\n      are that git-gui now sets a more evidently fake value for DISPLAY,\n      and the last patch has been acked.\n\n\nGIT-GUI:\n\n\tgit-gui: Add a dialog that shows the OpenSSH public key.\n\t---\n\t git-gui.sh     |    4 ++\n\t lib/sshkey.tcl |  126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\t 2 files changed, 130 insertions(+), 0 deletions(-)\n\t create mode 100644 lib/sshkey.tcl\n\n\tgit-gui: Add a simple implementation of SSH_ASKPASS.\n\t---\n\t Makefile         |    2 ++\n\t git-gui.sh       |   12 ++++++++++++\n\t git-gui--askpass |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\t 3 files changed, 73 insertions(+), 0 deletions(-)\n\t create mode 100755 git-gui--askpass\n\n\nCORE(MINGW):\n\n\tWindows: Make OpenSSH properly detect tty detachment.\n\t---\n\t compat/mingw.c |    8 ++++++--\n\t 1 files changed, 6 insertions(+), 2 deletions(-)\n"},{"id":"93510","messageId":"1224518540-23782-2-git-send-email-angavrilov@gmail.com","threadId":"15978","inReplyTo":"1224518540-23782-1-git-send-email-angavrilov@gmail.com","subject":"[PATCH (GIT-GUI,MINGW) 1/3] git-gui: Add a dialog that shows the OpenSSH public key.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-10-20T16:02:18Z","receivedAt":"2008-10-20T16:02:18Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"Generating a new SSH key or finding an existing one may\nbe a difficult task for non-technical users, especially\non Windows.\n\nThis commit adds a new dialog that shows the public key,\nor allows the user to generate a new one if none were found.\nSince this is a convenience/informational feature for new\nusers, and the dialog is mostly read-only, it is located\nin the Help menu.\n\nThe command line used to invoke ssh-keygen is designed to\nforce it to use SSH_ASKPASS if available, or accept empty\npassphrases, but _never_ wait for user response on the tty.\n\nSigned-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n---\n git-gui.sh     |    4 ++\n lib/sshkey.tcl |  126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 130 insertions(+), 0 deletions(-)\n create mode 100644 lib/sshkey.tcl\n\ndiff --git a/git-gui.sh b/git-gui.sh\nindex 4f95139..e4d1f70 100755\n--- a/git-gui.sh\n+++ b/git-gui.sh\n@@ -2536,6 +2536,10 @@ proc start_browser {url} {\n \n .mbar.help add command -label [mc \"Online Documentation\"] \\\n \t-command [list start_browser $doc_url]\n+\n+.mbar.help add command -label [mc \"Show SSH Key\"] \\\n+\t-command do_ssh_key\n+\n unset doc_path doc_url\n \n # -- Standard bindings\ndiff --git a/lib/sshkey.tcl b/lib/sshkey.tcl\nnew file mode 100644\nindex 0000000..82a1a80\n--- /dev/null\n+++ b/lib/sshkey.tcl\n@@ -0,0 +1,126 @@\n+# git-gui about git-gui dialog\n+# Copyright (C) 2006, 2007 Shawn Pearce\n+\n+proc find_ssh_key {} {\n+\tforeach name {~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub ~/.ssh/identity.pub} {\n+\t\tif {[file exists $name]} {\n+\t\t\tset fh    [open $name r]\n+\t\t\tset cont  [read $fh]\n+\t\t\tclose $fh\n+\t\t\treturn [list $name $cont]\n+\t\t}\n+\t}\n+\n+\treturn {}\n+}\n+\n+proc do_ssh_key {} {\n+\tglobal sshkey_title have_tk85 sshkey_fd\n+\n+\tset w .sshkey_dialog\n+\tif {[winfo exists $w]} {\n+\t\traise $w\n+\t\treturn\n+\t}\n+\n+\ttoplevel $w\n+\twm transient $w .\n+\n+\tset finfo [find_ssh_key]\n+\tif {$finfo eq {}} {\n+\t\tset sshkey_title [mc \"No keys found.\"]\n+\t\tset gen_state   normal\n+\t} else {\n+\t\tset sshkey_title [mc \"Found a public key in: %s\" [lindex $finfo 0]]\n+\t\tset gen_state   disabled\n+\t}\n+\n+\tframe $w.header -relief flat\n+\tlabel $w.header.lbl -textvariable sshkey_title -anchor w\n+\tbutton $w.header.gen -text [mc \"Generate Key\"] \\\n+\t\t-command [list make_ssh_key $w] -state $gen_state\n+\tpack $w.header.lbl -side left -expand 1 -fill x\n+\tpack $w.header.gen -side right\n+\tpack $w.header -fill x -pady 5 -padx 5\n+\n+\ttext $w.contents -width 60 -height 10 -wrap char -relief sunken\n+\tpack $w.contents -fill both -expand 1\n+\tif {$have_tk85} {\n+\t\t$w.contents configure -inactiveselectbackground darkblue\n+\t}\n+\n+\tframe $w.buttons\n+\tbutton $w.buttons.close -text [mc Close] \\\n+\t\t-default active -command [list destroy $w]\n+\tpack $w.buttons.close -side right\n+\tbutton $w.buttons.copy -text [mc \"Copy To Clipboard\"] \\\n+\t\t-command [list tk_textCopy $w.contents]\n+\tpack $w.buttons.copy -side left\n+\tpack $w.buttons -side bottom -fill x -pady 5 -padx 5\n+\n+\tif {$finfo ne {}} {\n+\t\t$w.contents insert end [lindex $finfo 1] sel\n+\t}\n+\t$w.contents configure -state disabled\n+\n+\tbind $w <Visibility> \"grab $w; focus $w.buttons.close\"\n+\tbind $w <Key-Escape> \"destroy $w\"\n+\tbind $w <Key-Return> \"destroy $w\"\n+\tbind $w <Destroy> kill_sshkey\n+\twm title $w [mc \"Your OpenSSH Public Key\"]\n+\ttk::PlaceWindow $w widget .\n+\ttkwait window $w\n+}\n+\n+proc make_ssh_key {w} {\n+\tglobal sshkey_title sshkey_output sshkey_fd\n+\n+\tset sshkey_title [mc \"Generating...\"]\n+\t$w.header.gen configure -state disabled\n+\n+\tset cmdline [list sh -c {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}]\n+\n+\tif {[catch { set sshkey_fd [_open_stdout_stderr $cmdline] } err]} {\n+\t\terror_popup [mc \"Could not start ssh-keygen:\\n\\n%s\" $err]\n+\t\treturn\n+\t}\n+\n+\tset sshkey_output {}\n+\tfconfigure $sshkey_fd -blocking 0\n+\tfileevent $sshkey_fd readable [list read_sshkey_output $sshkey_fd $w]\n+}\n+\n+proc kill_sshkey {} {\n+\tglobal sshkey_fd\n+\tif {![info exists sshkey_fd]} return\n+\tcatch { kill_file_process $sshkey_fd }\n+\tcatch { close $sshkey_fd }\n+}\n+\n+proc read_sshkey_output {fd w} {\n+\tglobal sshkey_fd sshkey_output sshkey_title\n+\n+\tset sshkey_output \"$sshkey_output[read $fd]\"\n+\tif {![eof $fd]} return\n+\n+\tfconfigure $fd -blocking 1\n+\tunset sshkey_fd\n+\n+\t$w.contents configure -state normal\n+\tif {[catch {close $fd} err]} {\n+\t\tset sshkey_title [mc \"Generation failed.\"]\n+\t\t$w.contents insert end $err\n+\t\t$w.contents insert end \"\\n\"\n+\t\t$w.contents insert end $sshkey_output\n+\t} else {\n+\t\tset finfo [find_ssh_key]\n+\t\tif {$finfo eq {}} {\n+\t\t\tset sshkey_title [mc \"Generation succeded, but no keys found.\"]\n+\t\t\t$w.contents insert end $sshkey_output\n+\t\t} else {\n+\t\t\tset sshkey_title [mc \"Your key is in: %s\" [lindex $finfo 0]]\n+\t\t\t$w.contents insert end [lindex $finfo 1] sel\n+\t\t}\n+\t}\n+\t$w.contents configure -state disable\n+}\n-- \n1.6.0.20.g6148bc\n"},{"id":"93509","messageId":"1224518540-23782-3-git-send-email-angavrilov@gmail.com","threadId":"15978","inReplyTo":"1224518540-23782-2-git-send-email-angavrilov@gmail.com","subject":"[PATCH (GIT-GUI,MINGW) 2/3] git-gui: Add a simple implementation of SSH_ASKPASS.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-10-20T16:02:19Z","receivedAt":"2008-10-20T16:02:19Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"OpenSSH allows specifying an external program to use\nfor direct user interaction. While most Linux systems\nalready have such programs, some environments, for\ninstance, msysgit, lack it. This patch adds a simple\nfallback Tcl implementation of the tool.\n\nIn msysgit it is also necessary to set a fake value of\nthe DISPLAY variable, because otherwise ssh won't even\ntry to use SSH_ASKPASS handlers.\n\nSigned-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n---\n Makefile         |    2 ++\n git-gui.sh       |   12 ++++++++++++\n git-gui--askpass |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 73 insertions(+), 0 deletions(-)\n create mode 100755 git-gui--askpass\n\ndiff --git a/Makefile b/Makefile\nindex 55765c8..0ee47bf 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -285,6 +285,7 @@ all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES)\n install: all\n \t$(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)\n \t$(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'\n+\t$(QUIET)$(INSTALL_X0)git-gui--askpass $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'\n \t$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true\n ifdef GITGUI_WINDOWS_WRAPPER\n \t$(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'\n@@ -302,6 +303,7 @@ endif\n uninstall:\n \t$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'\n \t$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)\n+\t$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askpass $(REMOVE_F1)\n \t$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true\n ifdef GITGUI_WINDOWS_WRAPPER\n \t$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1)\ndiff --git a/git-gui.sh b/git-gui.sh\nindex e4d1f70..5e04a7c 100755\n--- a/git-gui.sh\n+++ b/git-gui.sh\n@@ -592,6 +592,11 @@ bind . <Visibility> {\n if {[is_Windows]} {\n \twm iconbitmap . -default $oguilib/git-gui.ico\n \tset ::tk::AlwaysShowSelection 1\n+\n+\t# Spoof an X11 display for SSH\n+\tif {![info exists env(DISPLAY)]} {\n+\t\tset env(DISPLAY) :native\n+\t}\n }\n \n ######################################################################\n@@ -1071,6 +1076,13 @@ set nullid2 \"0000000000000000000000000000000000000001\"\n set have_tk85 [expr {[package vcompare $tk_version \"8.5\"] >= 0}]\n \n ######################################################################\n+\n+# Suggest our implementation of askpass, if not already set\n+if {![info exists env(SSH_ASKPASS)]} {\n+\tset env(SSH_ASKPASS) [gitexec git-gui--askpass]\n+}\n+\n+######################################################################\n ##\n ## task management\n \ndiff --git a/git-gui--askpass b/git-gui--askpass\nnew file mode 100755\nindex 0000000..12e117e\n--- /dev/null\n+++ b/git-gui--askpass\n@@ -0,0 +1,59 @@\n+#!/bin/sh\n+# Tcl ignores the next line -*- tcl -*- \\\n+exec wish \"$0\" -- \"$@\"\n+\n+# This is a trivial implementation of an SSH_ASKPASS handler.\n+# Git-gui uses this script if none are already configured.\n+\n+set answer {}\n+set yesno  0\n+set rc     255\n+\n+if {$argc < 1} {\n+\tset prompt \"Enter your OpenSSH passphrase:\"\n+} else {\n+\tset prompt [join $argv \" \"]\n+\tif {[regexp -nocase {\\(yes\\/no\\)\\?\\s*$} $prompt]} {\n+\t\tset yesno 1\n+\t}\n+}\n+\n+message .m -text $prompt -justify center -aspect 4000\n+pack .m -side top -fill x -padx 20 -pady 20 -expand 1\n+\n+entry .e -textvariable answer -width 50\n+pack .e -side top -fill x -padx 10 -pady 10\n+\n+if {!$yesno} {\n+\t.e configure -show \"*\"\n+}\n+\n+frame .b\n+button .b.ok     -text OK     -command finish\n+button .b.cancel -text Cancel -command {destroy .}\n+\n+pack .b.ok -side left -expand 1\n+pack .b.cancel -side right -expand 1\n+pack .b -side bottom -fill x -padx 10 -pady 10\n+\n+bind . <Visibility> {focus -force .e}\n+bind . <Key-Return> finish\n+bind . <Key-Escape> {destroy .}\n+bind . <Destroy>    {exit $rc}\n+\n+proc finish {} {\n+\tif {$::yesno} {\n+\t\tif {$::answer ne \"yes\" && $::answer ne \"no\"} {\n+\t\t\ttk_messageBox -icon error -title \"Error\" -type ok \\\n+\t\t\t\t-message \"Only 'yes' or 'no' input allowed.\"\n+\t\t\treturn\n+\t\t}\n+\t}\n+\n+\tset ::rc 0\n+\tputs $::answer\n+\tdestroy .\n+}\n+\n+wm title . \"OpenSSH\"\n+tk::PlaceWindow .\n-- \n1.6.0.20.g6148bc\n"},{"id":"93508","messageId":"1224518540-23782-4-git-send-email-angavrilov@gmail.com","threadId":"15978","inReplyTo":"1224518540-23782-3-git-send-email-angavrilov@gmail.com","subject":"[PATCH (GIT-GUI,MINGW) 3/3] Windows: Make OpenSSH properly detect tty detachment.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-10-20T16:02:20Z","receivedAt":"2008-10-20T16:02:20Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"Apparently, CREATE_NO_WINDOW makes the OS tell the process\nthat it has a console, but without actually creating the\nwindow. As a result, when git is started from GUI, ssh\ntries to ask its questions on the invisible console.\n\nThis patch uses DETACHED_PROCESS instead, which clearly\nmeans that the process should be left without a console.\nThe downside is that if the process manually calls\nAllocConsole, the window will appear. A similar thing\nmight occur if it calls another console executable.\n\nSigned-off-by: Alexander Gavrilov <angavrilov@gmail.com>\nAcked-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n compat/mingw.c |    8 ++++++--\n 1 files changed, 6 insertions(+), 2 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 1e29b88..b6fcf69 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -586,12 +586,16 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,\n \t\t * would normally create a console window. But\n \t\t * since we'll be redirecting std streams, we do\n \t\t * not need the console.\n+\t\t * It is necessary to use DETACHED_PROCESS\n+\t\t * instead of CREATE_NO_WINDOW to make ssh\n+\t\t * recognize that it has no console.\n \t\t */\n-\t\tflags = CREATE_NO_WINDOW;\n+\t\tflags = DETACHED_PROCESS;\n \t} else {\n \t\t/* There is already a console. If we specified\n-\t\t * CREATE_NO_WINDOW here, too, Windows would\n+\t\t * DETACHED_PROCESS here, too, Windows would\n \t\t * disassociate the child from the console.\n+\t\t * The same is true for CREATE_NO_WINDOW.\n \t\t * Go figure!\n \t\t */\n \t\tflags = 0;\n-- \n1.6.0.2.1256.ga12f0\n"}]}