00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "qca_support.h"
00022
00023 #include "qpipe.h"
00024 #include "qca_safeobj.h"
00025
00026 #include <QPointer>
00027 #include <QTextCodec>
00028 #include <QMutex>
00029
00030 #ifdef Q_OS_WIN
00031 # include <windows.h>
00032 #else
00033 # include <sys/termios.h>
00034 # include <unistd.h>
00035 # include <fcntl.h>
00036 # include <stdlib.h>
00037 #endif
00038
00039 #include <stdio.h>
00040
00041 #define CONSOLEPROMPT_INPUT_MAX 56
00042
00043 Q_DECLARE_METATYPE(QCA::SecureArray)
00044
00045 namespace QCA {
00046
00047
00048
00049
00050 class ConsoleWorker : public QObject
00051 {
00052 Q_OBJECT
00053 private:
00054 QPipeEnd in, out;
00055 bool started;
00056 QByteArray in_left, out_left;
00057
00058 public:
00059 ConsoleWorker(QObject *parent = 0) : QObject(parent), in(this), out(this)
00060 {
00061 started = false;
00062 }
00063
00064 ~ConsoleWorker()
00065 {
00066 stop();
00067 }
00068
00069 void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id)
00070 {
00071 Q_ASSERT(!started);
00072
00073 if(in_id != INVALID_Q_PIPE_ID)
00074 {
00075 in.take(in_id, QPipeDevice::Read);
00076 connect(&in, SIGNAL(readyRead()), SLOT(in_readyRead()));
00077 connect(&in, SIGNAL(closed()), SLOT(in_closed()));
00078 connect(&in, SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(in_error(QCA::QPipeEnd::Error)));
00079 in.enable();
00080 }
00081
00082 if(out_id != INVALID_Q_PIPE_ID)
00083 {
00084 out.take(out_id, QPipeDevice::Write);
00085 connect(&out, SIGNAL(bytesWritten(int)), SLOT(out_bytesWritten(int)));
00086 connect(&out, SIGNAL(closed()), SLOT(out_closed()));
00087 out.enable();
00088 }
00089
00090 started = true;
00091 }
00092
00093 void stop()
00094 {
00095 if(!started)
00096 return;
00097
00098 if(in.isValid())
00099 in.finalizeAndRelease();
00100 if(out.isValid())
00101 out.release();
00102
00103 in_left = in.read();
00104 out_left = out.takeBytesToWrite();
00105
00106 started = false;
00107 }
00108
00109 public slots:
00110 bool isValid() const
00111 {
00112 return in.isValid();
00113 }
00114
00115 void setSecurityEnabled(bool enabled)
00116 {
00117 if(in.isValid())
00118 in.setSecurityEnabled(enabled);
00119 if(out.isValid())
00120 out.setSecurityEnabled(enabled);
00121 }
00122
00123 QByteArray read(int bytes = -1)
00124 {
00125 return in.read(bytes);
00126 }
00127
00128 void write(const QByteArray &a)
00129 {
00130 out.write(a);
00131 }
00132
00133 QCA::SecureArray readSecure(int bytes = -1)
00134 {
00135 return in.readSecure(bytes);
00136 }
00137
00138 void writeSecure(const QCA::SecureArray &a)
00139 {
00140 out.writeSecure(a);
00141 }
00142
00143 void closeOutput()
00144 {
00145 out.close();
00146 }
00147
00148 int bytesAvailable() const
00149 {
00150 return in.bytesAvailable();
00151 }
00152
00153 int bytesToWrite() const
00154 {
00155 return in.bytesToWrite();
00156 }
00157
00158 public:
00159 QByteArray takeBytesToRead()
00160 {
00161 QByteArray a = in_left;
00162 in_left.clear();
00163 return a;
00164 }
00165
00166 QByteArray takeBytesToWrite()
00167 {
00168 QByteArray a = out_left;
00169 out_left.clear();
00170 return a;
00171 }
00172
00173 signals:
00174 void readyRead();
00175 void bytesWritten(int bytes);
00176 void inputClosed();
00177 void outputClosed();
00178
00179 private slots:
00180 void in_readyRead()
00181 {
00182 emit readyRead();
00183 }
00184
00185 void out_bytesWritten(int bytes)
00186 {
00187 emit bytesWritten(bytes);
00188 }
00189
00190 void in_closed()
00191 {
00192 emit inputClosed();
00193 }
00194
00195 void in_error(QCA::QPipeEnd::Error)
00196 {
00197 emit inputClosed();
00198 }
00199
00200 void out_closed()
00201 {
00202 emit outputClosed();
00203 }
00204 };
00205
00206
00207
00208
00209 class ConsoleThread : public SyncThread
00210 {
00211 Q_OBJECT
00212 public:
00213 ConsoleWorker *worker;
00214 Q_PIPE_ID _in_id, _out_id;
00215 QByteArray in_left, out_left;
00216 QMutex call_mutex;
00217
00218 ConsoleThread(QObject *parent = 0) : SyncThread(parent)
00219 {
00220 qRegisterMetaType<SecureArray>("QCA::SecureArray");
00221 }
00222
00223 ~ConsoleThread()
00224 {
00225 stop();
00226 }
00227
00228 void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id)
00229 {
00230 _in_id = in_id;
00231 _out_id = out_id;
00232 SyncThread::start();
00233 }
00234
00235 void stop()
00236 {
00237 SyncThread::stop();
00238 }
00239
00240 QVariant mycall(QObject *obj, const char *method, const QVariantList &args = QVariantList())
00241 {
00242 QVariant ret;
00243 bool ok;
00244
00245 call_mutex.lock();
00246 ret = call(obj, method, args, &ok);
00247 call_mutex.unlock();
00248
00249 Q_ASSERT(ok);
00250 if(!ok)
00251 {
00252 fprintf(stderr, "QCA: ConsoleWorker call [%s] failed.\n", method);
00253 abort();
00254 return QVariant();
00255 }
00256 return ret;
00257 }
00258
00259 bool isValid()
00260 {
00261 return mycall(worker, "isValid").toBool();
00262 }
00263
00264 void setSecurityEnabled(bool enabled)
00265 {
00266 mycall(worker, "setSecurityEnabled", QVariantList() << enabled);
00267 }
00268
00269 QByteArray read(int bytes = -1)
00270 {
00271 return mycall(worker, "read", QVariantList() << bytes).toByteArray();
00272 }
00273
00274 void write(const QByteArray &a)
00275 {
00276 mycall(worker, "write", QVariantList() << a);
00277 }
00278
00279 SecureArray readSecure(int bytes = -1)
00280 {
00281 return qVariantValue<SecureArray>(mycall(worker, "readSecure", QVariantList() << bytes));
00282 }
00283
00284 void writeSecure(const SecureArray &a)
00285 {
00286 mycall(worker, "writeSecure", QVariantList() << qVariantFromValue<SecureArray>(a));
00287 }
00288
00289 void closeOutput()
00290 {
00291 mycall(worker, "closeOutput");
00292 }
00293
00294 int bytesAvailable()
00295 {
00296 return mycall(worker, "bytesAvailable").toInt();
00297 }
00298
00299 int bytesToWrite()
00300 {
00301 return mycall(worker, "bytesToWrite").toInt();
00302 }
00303
00304 QByteArray takeBytesToRead()
00305 {
00306 QByteArray a = in_left;
00307 in_left.clear();
00308 return a;
00309 }
00310
00311 QByteArray takeBytesToWrite()
00312 {
00313 QByteArray a = out_left;
00314 out_left.clear();
00315 return a;
00316 }
00317
00318 signals:
00319 void readyRead();
00320 void bytesWritten(int);
00321 void inputClosed();
00322 void outputClosed();
00323
00324 protected:
00325 virtual void atStart()
00326 {
00327 worker = new ConsoleWorker;
00328
00329
00330
00331
00332 connect(worker, SIGNAL(readyRead()), SIGNAL(readyRead()), Qt::DirectConnection);
00333 connect(worker, SIGNAL(bytesWritten(int)), SIGNAL(bytesWritten(int)), Qt::DirectConnection);
00334 connect(worker, SIGNAL(inputClosed()), SIGNAL(inputClosed()), Qt::DirectConnection);
00335 connect(worker, SIGNAL(outputClosed()), SIGNAL(outputClosed()), Qt::DirectConnection);
00336
00337 worker->start(_in_id, _out_id);
00338 }
00339
00340 virtual void atEnd()
00341 {
00342 in_left = worker->takeBytesToRead();
00343 out_left = worker->takeBytesToWrite();
00344 delete worker;
00345 }
00346 };
00347
00348
00349
00350
00351 class ConsolePrivate : public QObject
00352 {
00353 Q_OBJECT
00354 public:
00355 Console *q;
00356
00357 bool started;
00358 Console::Type type;
00359 Console::ChannelMode cmode;
00360 Console::TerminalMode mode;
00361 ConsoleThread *thread;
00362 ConsoleReference *ref;
00363 Q_PIPE_ID in_id;
00364
00365 #ifdef Q_OS_WIN
00366 DWORD old_mode;
00367 #else
00368 struct termios old_term_attr;
00369 #endif
00370
00371 ConsolePrivate(Console *_q) : QObject(_q), q(_q)
00372 {
00373 started = false;
00374 mode = Console::Default;
00375 thread = new ConsoleThread(this);
00376 ref = 0;
00377 }
00378
00379 ~ConsolePrivate()
00380 {
00381 delete thread;
00382 setInteractive(Console::Default);
00383 }
00384
00385 void setInteractive(Console::TerminalMode m)
00386 {
00387
00388 if(m == mode)
00389 return;
00390
00391 if(m == Console::Interactive)
00392 {
00393 #ifdef Q_OS_WIN
00394 GetConsoleMode(in_id, &old_mode);
00395 SetConsoleMode(in_id, old_mode & (~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT));
00396 #else
00397 int fd = in_id;
00398 struct termios attr;
00399 tcgetattr(fd, &attr);
00400 old_term_attr = attr;
00401
00402 attr.c_lflag &= ~(ECHO);
00403 attr.c_lflag &= ~(ICANON);
00404 attr.c_cc[VMIN] = 1;
00405 attr.c_cc[VTIME] = 0;
00406
00407
00408 tcsetattr(fd, TCSAFLUSH, &attr);
00409 #endif
00410 }
00411 else
00412 {
00413 #ifdef Q_OS_WIN
00414 SetConsoleMode(in_id, old_mode);
00415 #else
00416 int fd = in_id;
00417 tcsetattr(fd, TCSANOW, &old_term_attr);
00418 #endif
00419 }
00420
00421 mode = m;
00422 }
00423 };
00424
00425 static Console *g_tty_console = 0, *g_stdio_console = 0;
00426
00427 Console::Console(Type type, ChannelMode cmode, TerminalMode tmode, QObject *parent)
00428 :QObject(parent)
00429 {
00430 if(type == Tty)
00431 {
00432 Q_ASSERT(g_tty_console == 0);
00433 g_tty_console = this;
00434 }
00435 else
00436 {
00437 Q_ASSERT(g_stdio_console == 0);
00438 g_stdio_console = this;
00439 }
00440
00441 d = new ConsolePrivate(this);
00442 d->type = type;
00443 d->cmode = cmode;
00444
00445 Q_PIPE_ID in = INVALID_Q_PIPE_ID;
00446 Q_PIPE_ID out = INVALID_Q_PIPE_ID;
00447
00448 #ifdef Q_OS_WIN
00449 if(type == Tty)
00450 {
00451 in = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE,
00452 FILE_SHARE_READ | FILE_SHARE_WRITE, false,
00453 OPEN_EXISTING, 0, NULL);
00454 }
00455 else
00456 {
00457 in = GetStdHandle(STD_INPUT_HANDLE);
00458 }
00459 #else
00460 if(type == Tty)
00461 {
00462 in = open("/dev/tty", O_RDONLY);
00463 }
00464 else
00465 {
00466 in = 0;
00467 }
00468 #endif
00469 if(cmode == ReadWrite)
00470 {
00471 #ifdef Q_OS_WIN
00472 if(type == Tty)
00473 {
00474 out = CreateFileA("CONOUT$",
00475 GENERIC_READ | GENERIC_WRITE,
00476 FILE_SHARE_READ | FILE_SHARE_WRITE, false,
00477 OPEN_EXISTING, 0, NULL);
00478 }
00479 else
00480 {
00481 out = GetStdHandle(STD_OUTPUT_HANDLE);
00482 }
00483 #else
00484 if(type == Tty)
00485 {
00486 out = open("/dev/tty", O_WRONLY);
00487 }
00488 else
00489 {
00490 out = 1;
00491 }
00492 #endif
00493 }
00494
00495 d->in_id = in;
00496 d->setInteractive(tmode);
00497 d->thread->start(in, out);
00498 }
00499
00500 Console::~Console()
00501 {
00502 release();
00503 Console::Type type = d->type;
00504 delete d;
00505 if(type == Tty)
00506 g_tty_console = 0;
00507 else
00508 g_stdio_console = 0;
00509 }
00510
00511 Console::Type Console::type() const
00512 {
00513 return d->type;
00514 }
00515
00516 Console::ChannelMode Console::channelMode() const
00517 {
00518 return d->cmode;
00519 }
00520
00521 Console::TerminalMode Console::terminalMode() const
00522 {
00523 return d->mode;
00524 }
00525
00526 bool Console::isStdinRedirected()
00527 {
00528 #ifdef Q_OS_WIN
00529 HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
00530 DWORD mode;
00531 if(GetConsoleMode(h, &mode))
00532 return false;
00533 return true;
00534 #else
00535 return (isatty(0) ? false : true);
00536 #endif
00537 }
00538
00539 bool Console::isStdoutRedirected()
00540 {
00541 #ifdef Q_OS_WIN
00542 HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
00543 DWORD mode;
00544 if(GetConsoleMode(h, &mode))
00545 return false;
00546 return true;
00547 #else
00548 return (isatty(1) ? false : true);
00549 #endif
00550 }
00551
00552 Console *Console::ttyInstance()
00553 {
00554 return g_tty_console;
00555 }
00556
00557 Console *Console::stdioInstance()
00558 {
00559 return g_stdio_console;
00560 }
00561
00562 void Console::release()
00563 {
00564 d->thread->stop();
00565 }
00566
00567 QByteArray Console::bytesLeftToRead()
00568 {
00569 return d->thread->takeBytesToRead();
00570 }
00571
00572 QByteArray Console::bytesLeftToWrite()
00573 {
00574 return d->thread->takeBytesToWrite();
00575 }
00576
00577
00578
00579
00580 class ConsoleReferencePrivate : public QObject
00581 {
00582 Q_OBJECT
00583 public:
00584 ConsoleReference *q;
00585
00586 Console *console;
00587 ConsoleThread *thread;
00588 ConsoleReference::SecurityMode smode;
00589 SafeTimer lateTrigger;
00590 bool late_read, late_close;
00591
00592 ConsoleReferencePrivate(ConsoleReference *_q) : QObject(_q), q(_q), lateTrigger(this)
00593 {
00594 console = 0;
00595 thread = 0;
00596 connect(&lateTrigger, SIGNAL(timeout()), SLOT(doLate()));
00597 lateTrigger.setSingleShot(true);
00598 }
00599
00600 private slots:
00601 void doLate()
00602 {
00603 QPointer<QObject> self = this;
00604 if(late_read)
00605 emit q->readyRead();
00606 if(!self)
00607 return;
00608 if(late_close)
00609 emit q->inputClosed();
00610 }
00611 };
00612
00613 ConsoleReference::ConsoleReference(QObject *parent)
00614 :QObject(parent)
00615 {
00616 d = new ConsoleReferencePrivate(this);
00617 }
00618
00619 ConsoleReference::~ConsoleReference()
00620 {
00621 stop();
00622 delete d;
00623 }
00624
00625 bool ConsoleReference::start(Console *console, SecurityMode mode)
00626 {
00627
00628 Q_ASSERT(!d->console);
00629
00630
00631 Q_ASSERT(console->d->ref == 0);
00632
00633
00634 d->console = console;
00635 d->thread = d->console->d->thread;
00636 d->console->d->ref = this;
00637
00638 bool valid = d->thread->isValid();
00639 int avail = d->thread->bytesAvailable();
00640
00641
00642 if(!valid && avail == 0)
00643 {
00644 d->console->d->ref = 0;
00645 d->thread = 0;
00646 d->console = 0;
00647 return false;
00648 }
00649
00650
00651 d->smode = mode;
00652 if(mode == SecurityEnabled)
00653 d->thread->setSecurityEnabled(true);
00654
00655 connect(d->thread, SIGNAL(readyRead()), SIGNAL(readyRead()));
00656 connect(d->thread, SIGNAL(bytesWritten(int)), SIGNAL(bytesWritten(int)));
00657 connect(d->thread, SIGNAL(inputClosed()), SIGNAL(inputClosed()));
00658 connect(d->thread, SIGNAL(outputClosed()), SIGNAL(outputClosed()));
00659
00660 d->late_read = false;
00661 d->late_close = false;
00662
00663 if(avail > 0)
00664 d->late_read = true;
00665
00666 if(!valid)
00667 d->late_close = true;
00668
00669 if(d->late_read || d->late_close)
00670 d->lateTrigger.start();
00671
00672 return true;
00673 }
00674
00675 void ConsoleReference::stop()
00676 {
00677 if(!d->console)
00678 return;
00679
00680 d->lateTrigger.stop();
00681
00682 disconnect(d->thread, 0, this, 0);
00683
00684
00685 d->thread->setSecurityEnabled(false);
00686
00687 d->console->d->ref = 0;
00688 d->thread = 0;
00689 d->console = 0;
00690 }
00691
00692 Console *ConsoleReference::console() const
00693 {
00694 return d->console;
00695 }
00696
00697 ConsoleReference::SecurityMode ConsoleReference::securityMode() const
00698 {
00699 return d->smode;
00700 }
00701
00702 QByteArray ConsoleReference::read(int bytes)
00703 {
00704 return d->thread->read(bytes);
00705 }
00706
00707 void ConsoleReference::write(const QByteArray &a)
00708 {
00709 d->thread->write(a);
00710 }
00711
00712 SecureArray ConsoleReference::readSecure(int bytes)
00713 {
00714 return d->thread->readSecure(bytes);
00715 }
00716
00717 void ConsoleReference::writeSecure(const SecureArray &a)
00718 {
00719 d->thread->writeSecure(a);
00720 }
00721
00722 void ConsoleReference::closeOutput()
00723 {
00724 d->thread->closeOutput();
00725 }
00726
00727 int ConsoleReference::bytesAvailable() const
00728 {
00729 return d->thread->bytesAvailable();
00730 }
00731
00732 int ConsoleReference::bytesToWrite() const
00733 {
00734 return d->thread->bytesToWrite();
00735 }
00736
00737
00738
00739
00740 class ConsolePrompt::Private : public QObject
00741 {
00742 Q_OBJECT
00743 public:
00744 ConsolePrompt *q;
00745
00746 Synchronizer sync;
00747 Console *con;
00748 bool own_con;
00749 ConsoleReference console;
00750 QString promptStr;
00751 SecureArray result;
00752 bool waiting;
00753 int at;
00754 bool done;
00755 bool charMode;
00756 QTextCodec *codec;
00757 QTextCodec::ConverterState *encstate, *decstate;
00758
00759 Private(ConsolePrompt *_q) : QObject(_q), q(_q), sync(_q), console(this)
00760 {
00761 connect(&console, SIGNAL(readyRead()), SLOT(con_readyRead()));
00762 connect(&console, SIGNAL(inputClosed()), SLOT(con_inputClosed()));
00763
00764 con = 0;
00765 own_con = false;
00766 waiting = false;
00767
00768 #ifdef Q_OS_WIN
00769 codec = QTextCodec::codecForMib(106);
00770 #else
00771 codec = QTextCodec::codecForLocale();
00772 #endif
00773 encstate = 0;
00774 decstate = 0;
00775 }
00776
00777 ~Private()
00778 {
00779 reset();
00780 }
00781
00782 void reset()
00783 {
00784 delete encstate;
00785 encstate = 0;
00786 delete decstate;
00787 decstate = 0;
00788
00789 console.stop();
00790 if(own_con)
00791 {
00792 delete con;
00793 con = 0;
00794 own_con = false;
00795 }
00796 }
00797
00798 bool start(bool _charMode)
00799 {
00800 own_con = false;
00801 con = Console::ttyInstance();
00802 if(!con)
00803 {
00804 con = new Console(Console::Tty, Console::ReadWrite, Console::Interactive);
00805 own_con = true;
00806 }
00807
00808 result.clear();
00809 at = 0;
00810 done = false;
00811 charMode = _charMode;
00812
00813 encstate = new QTextCodec::ConverterState(QTextCodec::IgnoreHeader);
00814 decstate = new QTextCodec::ConverterState(QTextCodec::IgnoreHeader);
00815
00816 if(!console.start(con, ConsoleReference::SecurityEnabled))
00817 {
00818 reset();
00819 fprintf(stderr, "Console input not available or closed\n");
00820 return false;
00821 }
00822
00823 if(!charMode)
00824 writeString(promptStr + ": ");
00825
00826 return true;
00827 }
00828
00829 void writeString(const QString &str)
00830 {
00831 console.writeSecure(codec->fromUnicode(str.unicode(), str.length(), encstate));
00832 }
00833
00834
00835
00836 bool processChar(QChar c)
00837 {
00838 if(charMode)
00839 {
00840 appendChar(c);
00841 done = true;
00842 return false;
00843 }
00844
00845 if(c == '\r' || c == '\n')
00846 {
00847 writeString("\n");
00848 done = true;
00849 return false;
00850 }
00851
00852 if(c == '\b' || c == 0x7f)
00853 {
00854 if(at > 0)
00855 {
00856 --at;
00857 writeString("\b \b");
00858 result.resize(at * sizeof(ushort));
00859 }
00860 return true;
00861 }
00862 else if(c < 0x20)
00863 return true;
00864
00865 if(at >= CONSOLEPROMPT_INPUT_MAX)
00866 return true;
00867
00868 appendChar(c);
00869
00870 writeString("*");
00871 return true;
00872 }
00873
00874 void appendChar(QChar c)
00875 {
00876 if((at + 1) * (int)sizeof(ushort) > result.size())
00877 result.resize((at + 1) * sizeof(ushort));
00878 ushort *p = (ushort *)result.data();
00879 p[at++] = c.unicode();
00880 }
00881
00882 void convertToUtf8()
00883 {
00884
00885 QTextCodec *codec = QTextCodec::codecForMib(106);
00886 QTextCodec::ConverterState cstate(QTextCodec::IgnoreHeader);
00887 SecureArray out;
00888 ushort *ustr = (ushort *)result.data();
00889 int len = result.size() / sizeof(ushort);
00890 for(int n = 0; n < len; ++n)
00891 {
00892 QChar c(ustr[n]);
00893 out += codec->fromUnicode(&c, 1, &cstate);
00894 }
00895 result = out;
00896 }
00897
00898 private slots:
00899 void con_readyRead()
00900 {
00901 while(console.bytesAvailable() > 0)
00902 {
00903 SecureArray buf = console.readSecure(1);
00904 if(buf.isEmpty())
00905 break;
00906
00907
00908 QString str = codec->toUnicode(buf.data(), 1, decstate);
00909 bool quit = false;
00910 for(int n = 0; n < str.length(); ++n)
00911 {
00912 if(!processChar(str[n]))
00913 {
00914 quit = true;
00915 break;
00916 }
00917 }
00918 if(quit)
00919 break;
00920 }
00921
00922 if(done)
00923 {
00924 convertToUtf8();
00925
00926 reset();
00927 if(waiting)
00928 sync.conditionMet();
00929 else
00930 emit q->finished();
00931 }
00932 }
00933
00934 void con_inputClosed()
00935 {
00936 fprintf(stderr, "Console input closed\n");
00937 if(!done)
00938 {
00939 done = true;
00940 result.clear();
00941
00942 reset();
00943 if(waiting)
00944 sync.conditionMet();
00945 else
00946 emit q->finished();
00947 }
00948 }
00949 };
00950
00951 ConsolePrompt::ConsolePrompt(QObject *parent)
00952 :QObject(parent)
00953 {
00954 d = new Private(this);
00955 }
00956
00957 ConsolePrompt::~ConsolePrompt()
00958 {
00959 delete d;
00960 }
00961
00962 void ConsolePrompt::getHidden(const QString &promptStr)
00963 {
00964 d->reset();
00965
00966 d->promptStr = promptStr;
00967 if(!d->start(false))
00968 {
00969 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
00970 return;
00971 }
00972 }
00973
00974 void ConsolePrompt::getChar()
00975 {
00976 d->reset();
00977
00978 if(!d->start(true))
00979 {
00980 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
00981 return;
00982 }
00983 }
00984
00985 void ConsolePrompt::waitForFinished()
00986 {
00987
00988 QObject *orig_parent = d->con->parent();
00989 d->con->setParent(this);
00990
00991
00992 d->waiting = true;
00993 d->sync.waitForCondition();
00994 d->waiting = false;
00995
00996
00997 if(d->con)
00998 d->con->setParent(orig_parent);
00999 }
01000
01001 SecureArray ConsolePrompt::result() const
01002 {
01003 return d->result;
01004 }
01005
01006 QChar ConsolePrompt::resultChar() const
01007 {
01008 QString str = QString::fromUtf8(d->result.toByteArray());
01009
01010
01011 if(str.isEmpty())
01012 return QChar();
01013
01014 return str[0];
01015 }
01016
01017 }
01018
01019 #include "console.moc"