… | |
… | |
406 | |
406 | |
407 | bool get (); |
407 | bool get (); |
408 | void login (int cmd_pid, bool login_shell, const char *hostname); |
408 | void login (int cmd_pid, bool login_shell, const char *hostname); |
409 | }; |
409 | }; |
410 | |
410 | |
|
|
411 | #if PTYTTY_REENTRANT |
|
|
412 | # define NEED_TOKEN do { char ch; read (lock_fd, &ch, 1); } while (0) |
|
|
413 | # define GIVE_TOKEN do { char ch; write (lock_fd, &ch, 1); } while (0) |
|
|
414 | #else |
|
|
415 | # define NEED_TOKEN (void)0 |
|
|
416 | # define GIVE_TOKEN (void)0 |
|
|
417 | #endif |
|
|
418 | |
411 | bool |
419 | bool |
412 | ptytty_proxy::get () |
420 | ptytty_proxy::get () |
413 | { |
421 | { |
|
|
422 | NEED_TOKEN; |
|
|
423 | |
414 | command cmd; |
424 | command cmd; |
415 | |
425 | |
416 | cmd.type = command::get; |
426 | cmd.type = command::get; |
417 | |
427 | |
418 | write (sock_fd, &cmd, sizeof (cmd)); |
428 | write (sock_fd, &cmd, sizeof (cmd)); |
419 | |
429 | |
420 | if (read (sock_fd, &id, sizeof (id)) != sizeof (id)) |
430 | if (read (sock_fd, &id, sizeof (id)) != sizeof (id)) |
421 | ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n"); |
431 | ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n"); |
422 | |
432 | |
423 | if (!id) |
433 | if (!id) |
|
|
434 | { |
|
|
435 | GIVE_TOKEN; |
424 | return false; |
436 | return false; |
|
|
437 | } |
425 | |
438 | |
426 | if ((pty = recv_fd (sock_fd)) < 0 |
439 | if ((pty = recv_fd (sock_fd)) < 0 |
427 | || (tty = recv_fd (sock_fd)) < 0) |
440 | || (tty = recv_fd (sock_fd)) < 0) |
428 | ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n"); |
441 | ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n"); |
429 | |
442 | |
|
|
443 | GIVE_TOKEN; |
430 | return true; |
444 | return true; |
431 | } |
445 | } |
432 | |
446 | |
433 | void |
447 | void |
434 | ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname) |
448 | ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname) |
435 | { |
449 | { |
|
|
450 | NEED_TOKEN; |
|
|
451 | |
436 | command cmd; |
452 | command cmd; |
437 | |
453 | |
438 | cmd.type = command::login; |
454 | cmd.type = command::login; |
439 | cmd.id = id; |
455 | cmd.id = id; |
440 | cmd.cmd_pid = cmd_pid; |
456 | cmd.cmd_pid = cmd_pid; |
441 | cmd.login_shell = login_shell; |
457 | cmd.login_shell = login_shell; |
442 | strncpy (cmd.hostname, hostname, sizeof (cmd.hostname)); |
458 | strncpy (cmd.hostname, hostname, sizeof (cmd.hostname)); |
443 | |
459 | |
444 | write (sock_fd, &cmd, sizeof (cmd)); |
460 | write (sock_fd, &cmd, sizeof (cmd)); |
|
|
461 | |
|
|
462 | GIVE_TOKEN; |
445 | } |
463 | } |
446 | |
464 | |
447 | ptytty_proxy::~ptytty_proxy () |
465 | ptytty_proxy::~ptytty_proxy () |
448 | { |
466 | { |
449 | if (id) |
467 | if (id) |
450 | { |
468 | { |
|
|
469 | NEED_TOKEN; |
|
|
470 | |
451 | command cmd; |
471 | command cmd; |
452 | |
472 | |
453 | cmd.type = command::destroy; |
473 | cmd.type = command::destroy; |
454 | cmd.id = id; |
474 | cmd.id = id; |
455 | |
475 | |
456 | write (sock_fd, &cmd, sizeof (cmd)); |
476 | write (sock_fd, &cmd, sizeof (cmd)); |
|
|
477 | |
|
|
478 | GIVE_TOKEN; |
457 | } |
479 | } |
458 | } |
480 | } |
459 | |
481 | |
460 | static |
482 | static |
461 | void serve () |
483 | void serve () |
462 | { |
484 | { |
463 | command cmd; |
485 | command cmd; |
464 | vector<ptytty *> ptys; |
486 | vector<ptytty *> ptys; |
465 | |
487 | |
|
|
488 | for (;;) |
|
|
489 | { |
|
|
490 | GIVE_TOKEN; |
|
|
491 | |
466 | while (read (sock_fd, &cmd, sizeof (command)) == sizeof (command)) |
492 | if (read (sock_fd, &cmd, sizeof (command)) != sizeof (command)) |
467 | { |
493 | break; |
|
|
494 | |
468 | if (cmd.type == command::get) |
495 | if (cmd.type == command::get) |
469 | { |
496 | { |
470 | // -> id ptyfd ttyfd |
497 | // -> id ptyfd ttyfd |
471 | cmd.id = new ptytty_unix; |
498 | cmd.id = new ptytty_unix; |
472 | |
499 | |
… | |
… | |
505 | ptys.erase (pty); |
532 | ptys.erase (pty); |
506 | } |
533 | } |
507 | } |
534 | } |
508 | else |
535 | else |
509 | break; |
536 | break; |
|
|
537 | |
|
|
538 | NEED_TOKEN; |
510 | } |
539 | } |
511 | |
540 | |
512 | // destroy all ptys |
541 | // destroy all ptys |
513 | for (vector<ptytty *>::iterator i = ptys.end (); i-- > ptys.begin (); ) |
542 | for (vector<ptytty *>::iterator i = ptys.end (); i-- > ptys.begin (); ) |
514 | delete *i; |
543 | delete *i; |
515 | } |
544 | } |
516 | |
545 | |
517 | void |
546 | void |
518 | ptytty::use_helper () |
547 | ptytty::use_helper () |
519 | { |
548 | { |
|
|
549 | #ifndef PTYTTY_NO_PID_CHECK |
520 | int pid = getpid (); |
550 | int pid = getpid (); |
|
|
551 | #endif |
521 | |
552 | |
522 | if (sock_fd >= 0 && pid == owner_pid) |
553 | if (sock_fd >= 0 |
|
|
554 | #ifndef PTYTTY_NO_PID_CHECK |
|
|
555 | && pid == owner_pid |
|
|
556 | #endif |
|
|
557 | ) |
523 | return; |
558 | return; |
524 | |
559 | |
|
|
560 | #ifndef PTYTTY_NO_PID_CHECK |
525 | owner_pid = pid; |
561 | owner_pid = pid; |
|
|
562 | #endif |
526 | |
563 | |
527 | int sv[2]; |
564 | int sv[2]; |
528 | |
565 | |
529 | if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv)) |
566 | if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv)) |
530 | ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n"); |
567 | ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n"); |
… | |
… | |
581 | |
618 | |
582 | ptytty * |
619 | ptytty * |
583 | ptytty::create () |
620 | ptytty::create () |
584 | { |
621 | { |
585 | #if PTYTTY_HELPER |
622 | #if PTYTTY_HELPER |
|
|
623 | if (helper_pid |
|
|
624 | # ifndef PTYTTY_NO_PID_CHECK |
586 | if (helper_pid && getpid () == owner_pid) |
625 | && getpid () == owner_pid |
|
|
626 | # endif |
|
|
627 | ) |
587 | // use helper process |
628 | // use helper process |
588 | return new ptytty_proxy; |
629 | return new ptytty_proxy; |
589 | else |
630 | else |
590 | #endif |
631 | #endif |
591 | return new ptytty_unix; |
632 | return new ptytty_unix; |
… | |
… | |
636 | } |
677 | } |
637 | |
678 | |
638 | ///////////////////////////////////////////////////////////////////////////// |
679 | ///////////////////////////////////////////////////////////////////////////// |
639 | // C API |
680 | // C API |
640 | |
681 | |
641 | #ifndef NO_C_API |
682 | #ifndef PTYTTY_NO_C_API |
642 | |
683 | |
643 | #define DEFINE_METHOD(retval, name, args1, args2) \ |
684 | #define DEFINE_METHOD(retval, name, args1, args2) \ |
644 | extern "C" retval ptytty_ ## name args1 \ |
685 | extern "C" retval ptytty_ ## name args1 \ |
645 | { return ((struct ptytty *)ptytty)->name args2; } |
686 | { return ((struct ptytty *)ptytty)->name args2; } |
646 | |
687 | |