comparison hgrunner.cpp @ 75:295e3ee4a257

* Allocate a pty for the subprocess, and ask the user for password. Very rudimentary and non-portable.
author Chris Cannam
date Fri, 19 Nov 2010 18:39:40 +0000
parents 10eb97683aa9
children d575a8f76a53
comparison
equal deleted inserted replaced
74:10eb97683aa9 75:295e3ee4a257
23 #include <QListWidget> 23 #include <QListWidget>
24 #include <QDialog> 24 #include <QDialog>
25 #include <QLabel> 25 #include <QLabel>
26 #include <QVBoxLayout> 26 #include <QVBoxLayout>
27 #include <QSettings> 27 #include <QSettings>
28 #include <QInputDialog>
28 29
29 #include <iostream> 30 #include <iostream>
30 #include <unistd.h> 31 #include <unistd.h>
32 #include <pty.h>
33 #include <errno.h>
34 #include <stdio.h>
31 35
32 HgRunner::HgRunner(QWidget * parent): QProgressBar(parent) 36 HgRunner::HgRunner(QWidget * parent): QProgressBar(parent)
33 { 37 {
34 proc = new QProcess(this); 38 proc = new QProcess(this);
35 39
43 isRunning = false; 47 isRunning = false;
44 48
45 stdOut.clear(); 49 stdOut.clear();
46 stdErr.clear(); 50 stdErr.clear();
47 51
52 procInput = 0;
53 char name[1024];
54 if (openpty(&ptyMasterFd, &ptySlaveFd, name, NULL, NULL)) {
55 perror("openpty failed");
56 } else {
57 DEBUG << "openpty succeeded: master " << ptyMasterFd
58 << " slave " << ptySlaveFd << " filename " << name << endl;
59 procInput = new QFile;
60 procInput->open(ptyMasterFd, QFile::WriteOnly);
61 ptySlaveFilename = name;
62 proc->setStandardInputFile(ptySlaveFilename);
63 ::close(ptySlaveFd);
64 }
65
48 connect(proc, SIGNAL(started()), this, SLOT(started())); 66 connect(proc, SIGNAL(started()), this, SLOT(started()));
49 connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), 67 connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)),
50 this, SLOT(finished(int, QProcess::ExitStatus))); 68 this, SLOT(finished(int, QProcess::ExitStatus)));
69 connect(proc, SIGNAL(readyReadStandardOutput()),
70 this, SLOT(stdOutReady()));
71 connect(proc, SIGNAL(readyReadStandardError()),
72 this, SLOT(stdErrReady()));
51 73
52 reportErrors = false; 74 reportErrors = false;
53 } 75 }
54 76
55 HgRunner::~HgRunner() 77 HgRunner::~HgRunner()
56 { 78 {
79 if (ptySlaveFilename != "") {
80 ::close(ptyMasterFd);
81 // ::close(ptySlaveFd);
82 }
57 delete proc; 83 delete proc;
58 } 84 }
59 85
60 QString HgRunner::getHgBinaryName() 86 QString HgRunner::getHgBinaryName()
61 { 87 {
67 return hg; 93 return hg;
68 } 94 }
69 95
70 void HgRunner::started() 96 void HgRunner::started()
71 { 97 {
98 /*
99 if (procInput) procInput->write("blah\n");
100 if (procInput) procInput->write("blah\n");
101 if (procInput) {
102 procInput->close();
103 // ::close(ptyMasterFd);
104 }
72 proc -> closeWriteChannel(); 105 proc -> closeWriteChannel();
106 */
73 } 107 }
74 108
75 void HgRunner::saveOutput() 109 void HgRunner::saveOutput()
76 { 110 {
77 stdOut = QString::fromUtf8(proc -> readAllStandardOutput()); 111 stdOut += QString::fromUtf8(proc -> readAllStandardOutput());
78 stdErr = QString::fromUtf8(proc -> readAllStandardError()); 112 stdErr += QString::fromUtf8(proc -> readAllStandardError());
79 113
80 DEBUG << "saveOutput: " << stdOut.split("\n").size() << " line(s) of stdout, " << stdErr.split("\n").size() << " line(s) of stderr" << endl; 114 DEBUG << "saveOutput: " << stdOut.split("\n").size() << " line(s) of stdout, " << stdErr.split("\n").size() << " line(s) of stderr" << endl;
81 115
82 // std::cerr << "stdout was " << stdOut.toStdString() << std::endl; 116 // std::cerr << "stdout was " << stdOut.toStdString() << std::endl;
83 } 117 }
89 } 123 }
90 124
91 QString HgRunner::getLastCommandLine() 125 QString HgRunner::getLastCommandLine()
92 { 126 {
93 return QString("Command line: " + lastHgCommand + " " + lastParams); 127 return QString("Command line: " + lastHgCommand + " " + lastParams);
128 }
129
130 void HgRunner::stdOutReady()
131 {
132 DEBUG << "stdOutReady" << endl;
133 QString chunk = QString::fromUtf8(proc->readAllStandardOutput());
134 DEBUG << "stdout was " << chunk << endl;
135 stdOut += chunk;
136 }
137
138 void HgRunner::stdErrReady()
139 {
140 DEBUG << "stdErrReady" << endl;
141 QString chunk = QString::fromUtf8(proc->readAllStandardError());
142 DEBUG << "stderr was " << chunk << endl;
143 stdErr += chunk;
144 if (procInput) {
145 if (chunk.toLower().trimmed() == "password:") {
146 bool ok = false;
147 QString pwd = QInputDialog::getText
148 (qobject_cast<QWidget *>(parent()),
149 tr("Enter password"), tr("Password (but for what user name and repository??"),
150 QLineEdit::Password, QString(), &ok);
151 if (ok) {
152 procInput->write(QString("%1\n").arg(pwd).toUtf8());
153 procInput->flush();
154 } else {
155 //!!! do what? close the terminal?
156 }
157 }
158 }
94 } 159 }
95 160
96 void HgRunner::finished(int procExitCode, QProcess::ExitStatus procExitStatus) 161 void HgRunner::finished(int procExitCode, QProcess::ExitStatus procExitStatus)
97 { 162 {
98 setProcExitInfo(procExitCode, procExitStatus); 163 setProcExitInfo(procExitCode, procExitStatus);