Changeset View
Changeset View
Standalone View
Standalone View
src/support/console.cpp
Show All 40 Lines | |||||
41 | 41 | | |||
42 | #include <stdio.h> | 42 | #include <stdio.h> | ||
43 | #include <stdlib.h> | 43 | #include <stdlib.h> | ||
44 | 44 | | |||
45 | #define CONSOLEPROMPT_INPUT_MAX 56 | 45 | #define CONSOLEPROMPT_INPUT_MAX 56 | ||
46 | 46 | | |||
47 | Q_DECLARE_METATYPE(QCA::SecureArray) | 47 | Q_DECLARE_METATYPE(QCA::SecureArray) | ||
48 | 48 | | |||
49 | namespace QCA { | 49 | namespace QCA | ||
50 | { | ||||
50 | 51 | | |||
51 | //---------------------------------------------------------------------------- | 52 | //---------------------------------------------------------------------------- | ||
52 | // ConsoleWorker | 53 | // ConsoleWorker | ||
53 | //---------------------------------------------------------------------------- | 54 | //---------------------------------------------------------------------------- | ||
54 | class ConsoleWorker : public QObject | 55 | class ConsoleWorker : public QObject | ||
55 | { | 56 | { | ||
56 | Q_OBJECT | 57 | Q_OBJECT | ||
57 | private: | 58 | private: | ||
Show All 11 Lines | 63 | public: | |||
69 | { | 70 | { | ||
70 | stop(); | 71 | stop(); | ||
71 | } | 72 | } | ||
72 | 73 | | |||
73 | void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id) | 74 | void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id) | ||
74 | { | 75 | { | ||
75 | Q_ASSERT(!started); | 76 | Q_ASSERT(!started); | ||
76 | 77 | | |||
77 | if(in_id != INVALID_Q_PIPE_ID) | 78 | if (in_id != INVALID_Q_PIPE_ID) { | ||
78 | { | | |||
79 | in.take(in_id, QPipeDevice::Read); | 79 | in.take(in_id, QPipeDevice::Read); | ||
80 | connect(&in, SIGNAL(readyRead()), SLOT(in_readyRead())); | 80 | connect(&in, SIGNAL(readyRead()), SLOT(in_readyRead())); | ||
81 | connect(&in, SIGNAL(closed()), SLOT(in_closed())); | 81 | connect(&in, SIGNAL(closed()), SLOT(in_closed())); | ||
82 | connect(&in, SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(in_error(QCA::QPipeEnd::Error))); | 82 | connect(&in, SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(in_error(QCA::QPipeEnd::Error))); | ||
83 | in.enable(); | 83 | in.enable(); | ||
84 | } | 84 | } | ||
85 | 85 | | |||
86 | if(out_id != INVALID_Q_PIPE_ID) | 86 | if (out_id != INVALID_Q_PIPE_ID) { | ||
87 | { | | |||
88 | out.take(out_id, QPipeDevice::Write); | 87 | out.take(out_id, QPipeDevice::Write); | ||
89 | connect(&out, SIGNAL(bytesWritten(int)), SLOT(out_bytesWritten(int))); | 88 | connect(&out, SIGNAL(bytesWritten(int)), SLOT(out_bytesWritten(int))); | ||
90 | connect(&out, SIGNAL(closed()), SLOT(out_closed())); | 89 | connect(&out, SIGNAL(closed()), SLOT(out_closed())); | ||
91 | out.enable(); | 90 | out.enable(); | ||
92 | } | 91 | } | ||
93 | 92 | | |||
94 | started = true; | 93 | started = true; | ||
95 | } | 94 | } | ||
96 | 95 | | |||
97 | void stop() | 96 | void stop() | ||
98 | { | 97 | { | ||
99 | if(!started) | 98 | if (!started) { | ||
100 | return; | 99 | return; | ||
100 | } | ||||
101 | 101 | | |||
102 | if(in.isValid()) | 102 | if (in.isValid()) { | ||
103 | in.finalizeAndRelease(); | 103 | in.finalizeAndRelease(); | ||
104 | if(out.isValid()) | 104 | } | ||
105 | if (out.isValid()) { | ||||
105 | out.release(); | 106 | out.release(); | ||
107 | } | ||||
106 | 108 | | |||
107 | in_left = in.read(); | 109 | in_left = in.read(); | ||
108 | out_left = out.takeBytesToWrite(); | 110 | out_left = out.takeBytesToWrite(); | ||
109 | 111 | | |||
110 | started = false; | 112 | started = false; | ||
111 | } | 113 | } | ||
112 | 114 | | |||
113 | public slots: | 115 | public slots: | ||
114 | bool isValid() const | 116 | bool isValid() const | ||
115 | { | 117 | { | ||
116 | return in.isValid(); | 118 | return in.isValid(); | ||
117 | } | 119 | } | ||
118 | 120 | | |||
119 | void setSecurityEnabled(bool enabled) | 121 | void setSecurityEnabled(bool enabled) | ||
120 | { | 122 | { | ||
121 | if(in.isValid()) | 123 | if (in.isValid()) { | ||
122 | in.setSecurityEnabled(enabled); | 124 | in.setSecurityEnabled(enabled); | ||
123 | if(out.isValid()) | 125 | } | ||
126 | if (out.isValid()) { | ||||
124 | out.setSecurityEnabled(enabled); | 127 | out.setSecurityEnabled(enabled); | ||
125 | } | 128 | } | ||
129 | } | ||||
126 | 130 | | |||
127 | QByteArray read(int bytes = -1) | 131 | QByteArray read(int bytes = -1) | ||
128 | { | 132 | { | ||
129 | return in.read(bytes); | 133 | return in.read(bytes); | ||
130 | } | 134 | } | ||
131 | 135 | | |||
132 | void write(const QByteArray &a) | 136 | void write(const QByteArray &a) | ||
133 | { | 137 | { | ||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Line(s) | 249 | { | |||
246 | QVariant ret; | 250 | QVariant ret; | ||
247 | bool ok; | 251 | bool ok; | ||
248 | 252 | | |||
249 | call_mutex.lock(); | 253 | call_mutex.lock(); | ||
250 | ret = call(obj, method, args, &ok); | 254 | ret = call(obj, method, args, &ok); | ||
251 | call_mutex.unlock(); | 255 | call_mutex.unlock(); | ||
252 | 256 | | |||
253 | Q_ASSERT(ok); | 257 | Q_ASSERT(ok); | ||
254 | if(!ok) | 258 | if (!ok) { | ||
255 | { | | |||
256 | fprintf(stderr, "QCA: ConsoleWorker call [%s] failed.\n", method); | 259 | fprintf(stderr, "QCA: ConsoleWorker call [%s] failed.\n", method); | ||
257 | abort(); | 260 | abort(); | ||
258 | return QVariant(); | 261 | return QVariant(); | ||
259 | } | 262 | } | ||
260 | return ret; | 263 | return ret; | ||
261 | } | 264 | } | ||
262 | 265 | | |||
263 | bool isValid() | 266 | bool isValid() | ||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Line(s) | 380 | #endif | |||
388 | { | 391 | { | ||
389 | delete thread; | 392 | delete thread; | ||
390 | setInteractive(Console::Default); | 393 | setInteractive(Console::Default); | ||
391 | } | 394 | } | ||
392 | 395 | | |||
393 | void setInteractive(Console::TerminalMode m) | 396 | void setInteractive(Console::TerminalMode m) | ||
394 | { | 397 | { | ||
395 | // no change | 398 | // no change | ||
396 | if(m == mode) | 399 | if (m == mode) { | ||
397 | return; | 400 | return; | ||
401 | } | ||||
398 | 402 | | |||
399 | if(m == Console::Interactive) | 403 | if (m == Console::Interactive) { | ||
400 | { | | |||
401 | #ifdef Q_OS_WIN | 404 | #ifdef Q_OS_WIN | ||
402 | GetConsoleMode(in_id, &old_mode); | 405 | GetConsoleMode(in_id, &old_mode); | ||
403 | SetConsoleMode(in_id, old_mode & (~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT)); | 406 | SetConsoleMode(in_id, old_mode & (~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT)); | ||
404 | #else | 407 | #else | ||
405 | int fd = in_id; | 408 | int fd = in_id; | ||
406 | struct termios attr; | 409 | struct termios attr; | ||
407 | tcgetattr(fd, &attr); | 410 | tcgetattr(fd, &attr); | ||
408 | old_term_attr = attr; | 411 | old_term_attr = attr; | ||
409 | 412 | | |||
410 | attr.c_lflag &= ~(ECHO); // turn off the echo flag | 413 | attr.c_lflag &= ~(ECHO); // turn off the echo flag | ||
411 | attr.c_lflag &= ~(ICANON); // no wait for a newline | 414 | attr.c_lflag &= ~(ICANON); // no wait for a newline | ||
412 | attr.c_cc[VMIN] = 1; // read at least 1 char | 415 | attr.c_cc[VMIN] = 1; // read at least 1 char | ||
413 | attr.c_cc[VTIME] = 0; // set wait time to zero | 416 | attr.c_cc[VTIME] = 0; // set wait time to zero | ||
414 | 417 | | |||
415 | // set the new attributes | 418 | // set the new attributes | ||
416 | tcsetattr(fd, TCSAFLUSH, &attr); | 419 | tcsetattr(fd, TCSAFLUSH, &attr); | ||
417 | #endif | 420 | #endif | ||
418 | } | 421 | } else { | ||
419 | else | | |||
420 | { | | |||
421 | #ifdef Q_OS_WIN | 422 | #ifdef Q_OS_WIN | ||
422 | SetConsoleMode(in_id, old_mode); | 423 | SetConsoleMode(in_id, old_mode); | ||
423 | #else | 424 | #else | ||
424 | int fd = in_id; | 425 | int fd = in_id; | ||
425 | tcsetattr(fd, TCSANOW, &old_term_attr); | 426 | tcsetattr(fd, TCSANOW, &old_term_attr); | ||
426 | #endif | 427 | #endif | ||
427 | } | 428 | } | ||
428 | 429 | | |||
429 | mode = m; | 430 | mode = m; | ||
430 | } | 431 | } | ||
431 | }; | 432 | }; | ||
432 | 433 | | |||
433 | static Console *g_tty_console = 0, *g_stdio_console = 0; | 434 | static Console *g_tty_console = 0, *g_stdio_console = 0; | ||
434 | 435 | | |||
435 | Console::Console(Type type, ChannelMode cmode, TerminalMode tmode, QObject *parent) | 436 | Console::Console(Type type, ChannelMode cmode, TerminalMode tmode, QObject *parent) | ||
436 | :QObject(parent) | 437 | : QObject(parent) | ||
437 | { | 438 | { | ||
438 | if(type == Tty) | 439 | if (type == Tty) { | ||
439 | { | | |||
440 | Q_ASSERT(g_tty_console == 0); | 440 | Q_ASSERT(g_tty_console == 0); | ||
441 | g_tty_console = this; | 441 | g_tty_console = this; | ||
442 | } | 442 | } else { | ||
443 | else | | |||
444 | { | | |||
445 | Q_ASSERT(g_stdio_console == 0); | 443 | Q_ASSERT(g_stdio_console == 0); | ||
446 | g_stdio_console = this; | 444 | g_stdio_console = this; | ||
447 | } | 445 | } | ||
448 | 446 | | |||
449 | d = new ConsolePrivate(this); | 447 | d = new ConsolePrivate(this); | ||
450 | d->type = type; | 448 | d->type = type; | ||
451 | d->cmode = cmode; | 449 | d->cmode = cmode; | ||
452 | 450 | | |||
453 | Q_PIPE_ID in = INVALID_Q_PIPE_ID; | 451 | Q_PIPE_ID in = INVALID_Q_PIPE_ID; | ||
454 | Q_PIPE_ID out = INVALID_Q_PIPE_ID; | 452 | Q_PIPE_ID out = INVALID_Q_PIPE_ID; | ||
455 | 453 | | |||
456 | #ifdef Q_OS_WIN | 454 | #ifdef Q_OS_WIN | ||
457 | if(type == Tty) | 455 | if (type == Tty) { | ||
458 | { | | |||
459 | in = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, | 456 | in = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, | ||
460 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | 457 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | ||
461 | OPEN_EXISTING, 0, NULL); | 458 | OPEN_EXISTING, 0, NULL); | ||
462 | } | 459 | } else { | ||
463 | else | | |||
464 | { | | |||
465 | in = GetStdHandle(STD_INPUT_HANDLE); | 460 | in = GetStdHandle(STD_INPUT_HANDLE); | ||
466 | } | 461 | } | ||
467 | #else | 462 | #else | ||
468 | if(type == Tty) | 463 | if (type == Tty) { | ||
469 | { | | |||
470 | in = open("/dev/tty", O_RDONLY); | 464 | in = open("/dev/tty", O_RDONLY); | ||
471 | } | 465 | } else { | ||
472 | else | | |||
473 | { | | |||
474 | in = 0; // stdin | 466 | in = 0; // stdin | ||
475 | } | 467 | } | ||
476 | #endif | 468 | #endif | ||
477 | if(cmode == ReadWrite) | 469 | if (cmode == ReadWrite) { | ||
478 | { | | |||
479 | #ifdef Q_OS_WIN | 470 | #ifdef Q_OS_WIN | ||
480 | if(type == Tty) | 471 | if (type == Tty) { | ||
481 | { | | |||
482 | out = CreateFileA("CONOUT$", | 472 | out = CreateFileA("CONOUT$", | ||
483 | GENERIC_READ | GENERIC_WRITE, | 473 | GENERIC_READ | GENERIC_WRITE, | ||
484 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | 474 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | ||
485 | OPEN_EXISTING, 0, NULL); | 475 | OPEN_EXISTING, 0, NULL); | ||
486 | } | 476 | } else { | ||
487 | else | | |||
488 | { | | |||
489 | out = GetStdHandle(STD_OUTPUT_HANDLE); | 477 | out = GetStdHandle(STD_OUTPUT_HANDLE); | ||
490 | } | 478 | } | ||
491 | #else | 479 | #else | ||
492 | if(type == Tty) | 480 | if (type == Tty) { | ||
493 | { | | |||
494 | out = open("/dev/tty", O_WRONLY); | 481 | out = open("/dev/tty", O_WRONLY); | ||
495 | } | 482 | } else { | ||
496 | else | | |||
497 | { | | |||
498 | out = 1; // stdout | 483 | out = 1; // stdout | ||
499 | } | 484 | } | ||
500 | #endif | 485 | #endif | ||
501 | } | 486 | } | ||
502 | 487 | | |||
503 | d->in_id = in; | 488 | d->in_id = in; | ||
504 | d->setInteractive(tmode); | 489 | d->setInteractive(tmode); | ||
505 | d->thread->start(in, out); | 490 | d->thread->start(in, out); | ||
506 | } | 491 | } | ||
507 | 492 | | |||
508 | Console::~Console() | 493 | Console::~Console() | ||
509 | { | 494 | { | ||
510 | release(); | 495 | release(); | ||
511 | Console::Type type = d->type; | 496 | Console::Type type = d->type; | ||
512 | delete d; | 497 | delete d; | ||
513 | if(type == Tty) | 498 | if (type == Tty) { | ||
514 | g_tty_console = 0; | 499 | g_tty_console = 0; | ||
515 | else | 500 | } else { | ||
516 | g_stdio_console = 0; | 501 | g_stdio_console = 0; | ||
517 | } | 502 | } | ||
503 | } | ||||
518 | 504 | | |||
519 | Console::Type Console::type() const | 505 | Console::Type Console::type() const | ||
520 | { | 506 | { | ||
521 | return d->type; | 507 | return d->type; | ||
522 | } | 508 | } | ||
523 | 509 | | |||
524 | Console::ChannelMode Console::channelMode() const | 510 | Console::ChannelMode Console::channelMode() const | ||
525 | { | 511 | { | ||
526 | return d->cmode; | 512 | return d->cmode; | ||
527 | } | 513 | } | ||
528 | 514 | | |||
529 | Console::TerminalMode Console::terminalMode() const | 515 | Console::TerminalMode Console::terminalMode() const | ||
530 | { | 516 | { | ||
531 | return d->mode; | 517 | return d->mode; | ||
532 | } | 518 | } | ||
533 | 519 | | |||
534 | bool Console::isStdinRedirected() | 520 | bool Console::isStdinRedirected() | ||
535 | { | 521 | { | ||
536 | #ifdef Q_OS_WIN | 522 | #ifdef Q_OS_WIN | ||
537 | HANDLE h = GetStdHandle(STD_INPUT_HANDLE); | 523 | HANDLE h = GetStdHandle(STD_INPUT_HANDLE); | ||
538 | DWORD mode; | 524 | DWORD mode; | ||
539 | if(GetConsoleMode(h, &mode)) | 525 | if (GetConsoleMode(h, &mode)) { | ||
540 | return false; | 526 | return false; | ||
527 | } | ||||
541 | return true; | 528 | return true; | ||
542 | #else | 529 | #else | ||
543 | return (isatty(0) ? false : true); // 0 == stdin | 530 | return (isatty(0) ? false : true); // 0 == stdin | ||
544 | #endif | 531 | #endif | ||
545 | } | 532 | } | ||
546 | 533 | | |||
547 | bool Console::isStdoutRedirected() | 534 | bool Console::isStdoutRedirected() | ||
548 | { | 535 | { | ||
549 | #ifdef Q_OS_WIN | 536 | #ifdef Q_OS_WIN | ||
550 | HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); | 537 | HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); | ||
551 | DWORD mode; | 538 | DWORD mode; | ||
552 | if(GetConsoleMode(h, &mode)) | 539 | if (GetConsoleMode(h, &mode)) { | ||
553 | return false; | 540 | return false; | ||
541 | } | ||||
554 | return true; | 542 | return true; | ||
555 | #else | 543 | #else | ||
556 | return (isatty(1) ? false : true); // 1 == stdout | 544 | return (isatty(1) ? false : true); // 1 == stdout | ||
557 | #endif | 545 | #endif | ||
558 | } | 546 | } | ||
559 | 547 | | |||
560 | Console *Console::ttyInstance() | 548 | Console *Console::ttyInstance() | ||
561 | { | 549 | { | ||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Line(s) | 589 | { | |||
604 | connect(&lateTrigger, SIGNAL(timeout()), SLOT(doLate())); | 592 | connect(&lateTrigger, SIGNAL(timeout()), SLOT(doLate())); | ||
605 | lateTrigger.setSingleShot(true); | 593 | lateTrigger.setSingleShot(true); | ||
606 | } | 594 | } | ||
607 | 595 | | |||
608 | private slots: | 596 | private slots: | ||
609 | void doLate() | 597 | void doLate() | ||
610 | { | 598 | { | ||
611 | QPointer<QObject> self = this; | 599 | QPointer<QObject> self = this; | ||
612 | if(late_read) | 600 | if (late_read) { | ||
613 | emit q->readyRead(); | 601 | emit q->readyRead(); | ||
614 | if(!self) | 602 | } | ||
603 | if (!self) { | ||||
615 | return; | 604 | return; | ||
616 | if(late_close) | 605 | } | ||
606 | if (late_close) { | ||||
617 | emit q->inputClosed(); | 607 | emit q->inputClosed(); | ||
618 | } | 608 | } | ||
609 | } | ||||
619 | }; | 610 | }; | ||
620 | 611 | | |||
621 | ConsoleReference::ConsoleReference(QObject *parent) | 612 | ConsoleReference::ConsoleReference(QObject *parent) | ||
622 | :QObject(parent) | 613 | : QObject(parent) | ||
623 | { | 614 | { | ||
624 | d = new ConsoleReferencePrivate(this); | 615 | d = new ConsoleReferencePrivate(this); | ||
625 | } | 616 | } | ||
626 | 617 | | |||
627 | ConsoleReference::~ConsoleReference() | 618 | ConsoleReference::~ConsoleReference() | ||
628 | { | 619 | { | ||
629 | stop(); | 620 | stop(); | ||
630 | delete d; | 621 | delete d; | ||
Show All 11 Lines | 625 | { | |||
642 | d->console = console; | 633 | d->console = console; | ||
643 | d->thread = d->console->d->thread; | 634 | d->thread = d->console->d->thread; | ||
644 | d->console->d->ref = this; | 635 | d->console->d->ref = this; | ||
645 | 636 | | |||
646 | bool valid = d->thread->isValid(); | 637 | bool valid = d->thread->isValid(); | ||
647 | int avail = d->thread->bytesAvailable(); | 638 | int avail = d->thread->bytesAvailable(); | ||
648 | 639 | | |||
649 | // pipe already closed and no data? consider this an error | 640 | // pipe already closed and no data? consider this an error | ||
650 | if(!valid && avail == 0) | 641 | if (!valid && avail == 0) { | ||
651 | { | | |||
652 | d->console->d->ref = 0; | 642 | d->console->d->ref = 0; | ||
653 | d->thread = 0; | 643 | d->thread = 0; | ||
654 | d->console = 0; | 644 | d->console = 0; | ||
655 | return false; | 645 | return false; | ||
656 | } | 646 | } | ||
657 | 647 | | |||
658 | // enable security? it will last for this active session only | 648 | // enable security? it will last for this active session only | ||
659 | d->smode = mode; | 649 | d->smode = mode; | ||
660 | if(mode == SecurityEnabled) | 650 | if (mode == SecurityEnabled) { | ||
661 | d->thread->setSecurityEnabled(true); | 651 | d->thread->setSecurityEnabled(true); | ||
652 | } | ||||
662 | 653 | | |||
663 | connect(d->thread, SIGNAL(readyRead()), SIGNAL(readyRead())); | 654 | connect(d->thread, SIGNAL(readyRead()), SIGNAL(readyRead())); | ||
664 | connect(d->thread, SIGNAL(bytesWritten(int)), SIGNAL(bytesWritten(int))); | 655 | connect(d->thread, SIGNAL(bytesWritten(int)), SIGNAL(bytesWritten(int))); | ||
665 | connect(d->thread, SIGNAL(inputClosed()), SIGNAL(inputClosed())); | 656 | connect(d->thread, SIGNAL(inputClosed()), SIGNAL(inputClosed())); | ||
666 | connect(d->thread, SIGNAL(outputClosed()), SIGNAL(outputClosed())); | 657 | connect(d->thread, SIGNAL(outputClosed()), SIGNAL(outputClosed())); | ||
667 | 658 | | |||
668 | d->late_read = false; | 659 | d->late_read = false; | ||
669 | d->late_close = false; | 660 | d->late_close = false; | ||
670 | 661 | | |||
671 | if(avail > 0) | 662 | if (avail > 0) { | ||
672 | d->late_read = true; | 663 | d->late_read = true; | ||
664 | } | ||||
673 | 665 | | |||
674 | if(!valid) | 666 | if (!valid) { | ||
675 | d->late_close = true; | 667 | d->late_close = true; | ||
668 | } | ||||
676 | 669 | | |||
677 | if(d->late_read || d->late_close) | 670 | if (d->late_read || d->late_close) { | ||
678 | d->lateTrigger.start(); | 671 | d->lateTrigger.start(); | ||
672 | } | ||||
679 | 673 | | |||
680 | return true; | 674 | return true; | ||
681 | } | 675 | } | ||
682 | 676 | | |||
683 | void ConsoleReference::stop() | 677 | void ConsoleReference::stop() | ||
684 | { | 678 | { | ||
685 | if(!d->console) | 679 | if (!d->console) { | ||
686 | return; | 680 | return; | ||
681 | } | ||||
687 | 682 | | |||
688 | d->lateTrigger.stop(); | 683 | d->lateTrigger.stop(); | ||
689 | 684 | | |||
690 | disconnect(d->thread, 0, this, 0); | 685 | disconnect(d->thread, 0, this, 0); | ||
691 | 686 | | |||
692 | // automatically disable security when we go inactive | 687 | // automatically disable security when we go inactive | ||
693 | d->thread->setSecurityEnabled(false); | 688 | d->thread->setSecurityEnabled(false); | ||
694 | 689 | | |||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Line(s) | 775 | #endif | |||
790 | void reset() | 785 | void reset() | ||
791 | { | 786 | { | ||
792 | delete encstate; | 787 | delete encstate; | ||
793 | encstate = 0; | 788 | encstate = 0; | ||
794 | delete decstate; | 789 | delete decstate; | ||
795 | decstate = 0; | 790 | decstate = 0; | ||
796 | 791 | | |||
797 | console.stop(); | 792 | console.stop(); | ||
798 | if(own_con) | 793 | if (own_con) { | ||
799 | { | | |||
800 | delete con; | 794 | delete con; | ||
801 | con = 0; | 795 | con = 0; | ||
802 | own_con = false; | 796 | own_con = false; | ||
803 | } | 797 | } | ||
804 | } | 798 | } | ||
805 | 799 | | |||
806 | bool start(bool _charMode) | 800 | bool start(bool _charMode) | ||
807 | { | 801 | { | ||
808 | own_con = false; | 802 | own_con = false; | ||
809 | con = Console::ttyInstance(); | 803 | con = Console::ttyInstance(); | ||
810 | if(!con) | 804 | if (!con) { | ||
811 | { | | |||
812 | con = new Console(Console::Tty, Console::ReadWrite, Console::Interactive); | 805 | con = new Console(Console::Tty, Console::ReadWrite, Console::Interactive); | ||
813 | own_con = true; | 806 | own_con = true; | ||
814 | } | 807 | } | ||
815 | 808 | | |||
816 | result.clear(); | 809 | result.clear(); | ||
817 | at = 0; | 810 | at = 0; | ||
818 | done = false; | 811 | done = false; | ||
819 | charMode = _charMode; | 812 | charMode = _charMode; | ||
820 | 813 | | |||
821 | encstate = new QTextCodec::ConverterState(QTextCodec::IgnoreHeader); | 814 | encstate = new QTextCodec::ConverterState(QTextCodec::IgnoreHeader); | ||
822 | decstate = new QTextCodec::ConverterState(QTextCodec::IgnoreHeader); | 815 | decstate = new QTextCodec::ConverterState(QTextCodec::IgnoreHeader); | ||
823 | 816 | | |||
824 | if(!console.start(con, ConsoleReference::SecurityEnabled)) | 817 | if (!console.start(con, ConsoleReference::SecurityEnabled)) { | ||
825 | { | | |||
826 | reset(); | 818 | reset(); | ||
827 | fprintf(stderr, "Console input not available or closed\n"); | 819 | fprintf(stderr, "Console input not available or closed\n"); | ||
828 | return false; | 820 | return false; | ||
829 | } | 821 | } | ||
830 | 822 | | |||
831 | if(!charMode) | 823 | if (!charMode) { | ||
832 | writeString(promptStr + ": "); | 824 | writeString(promptStr + ": "); | ||
825 | } | ||||
833 | 826 | | |||
834 | return true; | 827 | return true; | ||
835 | } | 828 | } | ||
836 | 829 | | |||
837 | void writeString(const QString &str) | 830 | void writeString(const QString &str) | ||
838 | { | 831 | { | ||
839 | console.writeSecure(codec->fromUnicode(str.unicode(), str.length(), encstate)); | 832 | console.writeSecure(codec->fromUnicode(str.unicode(), str.length(), encstate)); | ||
840 | } | 833 | } | ||
841 | 834 | | |||
842 | // process each char. internally store the result as utf16, which | 835 | // process each char. internally store the result as utf16, which | ||
843 | // is easier to edit (e.g. backspace) | 836 | // is easier to edit (e.g. backspace) | ||
844 | bool processChar(QChar c) | 837 | bool processChar(QChar c) | ||
845 | { | 838 | { | ||
846 | if(charMode) | 839 | if (charMode) { | ||
847 | { | | |||
848 | appendChar(c); | 840 | appendChar(c); | ||
849 | done = true; | 841 | done = true; | ||
850 | return false; | 842 | return false; | ||
851 | } | 843 | } | ||
852 | 844 | | |||
853 | if(c == '\r' || c == '\n') | 845 | if (c == '\r' || c == '\n') { | ||
854 | { | | |||
855 | writeString("\n"); | 846 | writeString("\n"); | ||
856 | done = true; | 847 | done = true; | ||
857 | return false; | 848 | return false; | ||
858 | } | 849 | } | ||
859 | 850 | | |||
860 | if(c == '\b' || c.unicode() == 0x7f) | 851 | if (c == '\b' || c.unicode() == 0x7f) { | ||
861 | { | 852 | if (at > 0) { | ||
862 | if(at > 0) | | |||
863 | { | | |||
864 | --at; | 853 | --at; | ||
865 | writeString("\b \b"); | 854 | writeString("\b \b"); | ||
866 | result.resize(at * sizeof(ushort)); | 855 | result.resize(at * sizeof(ushort)); | ||
867 | } | 856 | } | ||
868 | return true; | 857 | return true; | ||
869 | } | 858 | } else if (c < 0x20) { | ||
870 | else if(c < 0x20) | | |||
871 | return true; | 859 | return true; | ||
860 | } | ||||
872 | 861 | | |||
873 | if(at >= CONSOLEPROMPT_INPUT_MAX) | 862 | if (at >= CONSOLEPROMPT_INPUT_MAX) { | ||
874 | return true; | 863 | return true; | ||
864 | } | ||||
875 | 865 | | |||
876 | appendChar(c); | 866 | appendChar(c); | ||
877 | 867 | | |||
878 | writeString("*"); | 868 | writeString("*"); | ||
879 | return true; | 869 | return true; | ||
880 | } | 870 | } | ||
881 | 871 | | |||
882 | void appendChar(QChar c) | 872 | void appendChar(QChar c) | ||
883 | { | 873 | { | ||
884 | if((at + 1) * (int)sizeof(ushort) > result.size()) | 874 | if ((at + 1) * (int)sizeof(ushort) > result.size()) { | ||
885 | result.resize((at + 1) * sizeof(ushort)); | 875 | result.resize((at + 1) * sizeof(ushort)); | ||
876 | } | ||||
886 | ushort *p = (ushort *)result.data(); | 877 | ushort *p = (ushort *)result.data(); | ||
887 | p[at++] = c.unicode(); | 878 | p[at++] = c.unicode(); | ||
888 | } | 879 | } | ||
889 | 880 | | |||
890 | void convertToUtf8() | 881 | void convertToUtf8() | ||
891 | { | 882 | { | ||
892 | // convert result from utf16 to utf8, securely | 883 | // convert result from utf16 to utf8, securely | ||
893 | QTextCodec *codec = QTextCodec::codecForMib(106); | 884 | QTextCodec *codec = QTextCodec::codecForMib(106); | ||
894 | QTextCodec::ConverterState cstate(QTextCodec::IgnoreHeader); | 885 | QTextCodec::ConverterState cstate(QTextCodec::IgnoreHeader); | ||
895 | SecureArray out; | 886 | SecureArray out; | ||
896 | ushort *ustr = (ushort *)result.data(); | 887 | ushort *ustr = (ushort *)result.data(); | ||
897 | int len = result.size() / sizeof(ushort); | 888 | int len = result.size() / sizeof(ushort); | ||
898 | for(int n = 0; n < len; ++n) | 889 | for (int n = 0; n < len; ++n) { | ||
899 | { | | |||
900 | QChar c(ustr[n]); | 890 | QChar c(ustr[n]); | ||
901 | out += codec->fromUnicode(&c, 1, &cstate); | 891 | out += codec->fromUnicode(&c, 1, &cstate); | ||
902 | } | 892 | } | ||
903 | result = out; | 893 | result = out; | ||
904 | } | 894 | } | ||
905 | 895 | | |||
906 | private slots: | 896 | private slots: | ||
907 | void con_readyRead() | 897 | void con_readyRead() | ||
908 | { | 898 | { | ||
909 | while(console.bytesAvailable() > 0) | 899 | while (console.bytesAvailable() > 0) { | ||
910 | { | | |||
911 | SecureArray buf = console.readSecure(1); | 900 | SecureArray buf = console.readSecure(1); | ||
912 | if(buf.isEmpty()) | 901 | if (buf.isEmpty()) { | ||
913 | break; | 902 | break; | ||
903 | } | ||||
914 | 904 | | |||
915 | // convert to unicode and process | 905 | // convert to unicode and process | ||
916 | QString str = codec->toUnicode(buf.data(), 1, decstate); | 906 | QString str = codec->toUnicode(buf.data(), 1, decstate); | ||
917 | bool quit = false; | 907 | bool quit = false; | ||
918 | for(int n = 0; n < str.length(); ++n) | 908 | for (int n = 0; n < str.length(); ++n) { | ||
919 | { | 909 | if (!processChar(str[n])) { | ||
920 | if(!processChar(str[n])) | | |||
921 | { | | |||
922 | quit = true; | 910 | quit = true; | ||
923 | break; | 911 | break; | ||
924 | } | 912 | } | ||
925 | } | 913 | } | ||
926 | if(quit) | 914 | if (quit) { | ||
927 | break; | 915 | break; | ||
928 | } | 916 | } | ||
917 | } | ||||
929 | 918 | | |||
930 | if(done) | 919 | if (done) { | ||
931 | { | | |||
932 | convertToUtf8(); | 920 | convertToUtf8(); | ||
933 | 921 | | |||
934 | reset(); | 922 | reset(); | ||
935 | if(waiting) | 923 | if (waiting) { | ||
936 | sync.conditionMet(); | 924 | sync.conditionMet(); | ||
937 | else | 925 | } else { | ||
938 | emit q->finished(); | 926 | emit q->finished(); | ||
939 | } | 927 | } | ||
940 | } | 928 | } | ||
929 | } | ||||
941 | 930 | | |||
942 | void con_inputClosed() | 931 | void con_inputClosed() | ||
943 | { | 932 | { | ||
944 | fprintf(stderr, "Console input closed\n"); | 933 | fprintf(stderr, "Console input closed\n"); | ||
945 | if(!done) | 934 | if (!done) { | ||
946 | { | | |||
947 | done = true; | 935 | done = true; | ||
948 | result.clear(); | 936 | result.clear(); | ||
949 | 937 | | |||
950 | reset(); | 938 | reset(); | ||
951 | if(waiting) | 939 | if (waiting) { | ||
952 | sync.conditionMet(); | 940 | sync.conditionMet(); | ||
953 | else | 941 | } else { | ||
954 | emit q->finished(); | 942 | emit q->finished(); | ||
955 | } | 943 | } | ||
956 | } | 944 | } | ||
945 | } | ||||
957 | }; | 946 | }; | ||
958 | 947 | | |||
959 | ConsolePrompt::ConsolePrompt(QObject *parent) | 948 | ConsolePrompt::ConsolePrompt(QObject *parent) | ||
960 | :QObject(parent) | 949 | : QObject(parent) | ||
961 | { | 950 | { | ||
962 | d = new Private(this); | 951 | d = new Private(this); | ||
963 | } | 952 | } | ||
964 | 953 | | |||
965 | ConsolePrompt::~ConsolePrompt() | 954 | ConsolePrompt::~ConsolePrompt() | ||
966 | { | 955 | { | ||
967 | delete d; | 956 | delete d; | ||
968 | } | 957 | } | ||
969 | 958 | | |||
970 | void ConsolePrompt::getHidden(const QString &promptStr) | 959 | void ConsolePrompt::getHidden(const QString &promptStr) | ||
971 | { | 960 | { | ||
972 | d->reset(); | 961 | d->reset(); | ||
973 | 962 | | |||
974 | d->promptStr = promptStr; | 963 | d->promptStr = promptStr; | ||
975 | if(!d->start(false)) | 964 | if (!d->start(false)) { | ||
976 | { | | |||
977 | QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); | 965 | QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); | ||
978 | return; | 966 | return; | ||
979 | } | 967 | } | ||
980 | } | 968 | } | ||
981 | 969 | | |||
982 | void ConsolePrompt::getChar() | 970 | void ConsolePrompt::getChar() | ||
983 | { | 971 | { | ||
984 | d->reset(); | 972 | d->reset(); | ||
985 | 973 | | |||
986 | if(!d->start(true)) | 974 | if (!d->start(true)) { | ||
987 | { | | |||
988 | QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); | 975 | QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); | ||
989 | return; | 976 | return; | ||
990 | } | 977 | } | ||
991 | } | 978 | } | ||
992 | 979 | | |||
993 | void ConsolePrompt::waitForFinished() | 980 | void ConsolePrompt::waitForFinished() | ||
994 | { | 981 | { | ||
995 | // reparent the Console under us (for Synchronizer) | 982 | // reparent the Console under us (for Synchronizer) | ||
996 | QObject *orig_parent = d->con->parent(); | 983 | QObject *orig_parent = d->con->parent(); | ||
997 | d->con->setParent(this); | 984 | d->con->setParent(this); | ||
998 | 985 | | |||
999 | // block while prompting | 986 | // block while prompting | ||
1000 | d->waiting = true; | 987 | d->waiting = true; | ||
1001 | d->sync.waitForCondition(); | 988 | d->sync.waitForCondition(); | ||
1002 | d->waiting = false; | 989 | d->waiting = false; | ||
1003 | 990 | | |||
1004 | // restore parent (if con still exists) | 991 | // restore parent (if con still exists) | ||
1005 | if(d->con) | 992 | if (d->con) { | ||
1006 | d->con->setParent(orig_parent); | 993 | d->con->setParent(orig_parent); | ||
1007 | } | 994 | } | ||
995 | } | ||||
1008 | 996 | | |||
1009 | SecureArray ConsolePrompt::result() const | 997 | SecureArray ConsolePrompt::result() const | ||
1010 | { | 998 | { | ||
1011 | return d->result; | 999 | return d->result; | ||
1012 | } | 1000 | } | ||
1013 | 1001 | | |||
1014 | QChar ConsolePrompt::resultChar() const | 1002 | QChar ConsolePrompt::resultChar() const | ||
1015 | { | 1003 | { | ||
1016 | QString str = QString::fromUtf8(d->result.toByteArray()); | 1004 | QString str = QString::fromUtf8(d->result.toByteArray()); | ||
1017 | 1005 | | |||
1018 | // this will never happen if getChar completes | 1006 | // this will never happen if getChar completes | ||
1019 | if(str.isEmpty()) | 1007 | if (str.isEmpty()) { | ||
1020 | return QChar(); | 1008 | return QChar(); | ||
1009 | } | ||||
1021 | 1010 | | |||
1022 | return str[0]; | 1011 | return str[0]; | ||
1023 | } | 1012 | } | ||
1024 | 1013 | | |||
1025 | } | 1014 | } | ||
1026 | 1015 | | |||
1027 | #include "console.moc" | 1016 | #include "console.moc" |