Class: HrrRbSsh::Connection::RequestHandler::ReferenceShellRequestHandler

Inherits:
HrrRbSsh::Connection::RequestHandler show all
Defined in:
lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb

Instance Method Summary collapse

Methods inherited from HrrRbSsh::Connection::RequestHandler

#run

Constructor Details

#initializeReferenceShellRequestHandler

Returns a new instance of ReferenceShellRequestHandler.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb', line 12

def initialize
  @proc = Proc.new { |context|
    ptm = context.vars[:ptm]
    pts = context.vars[:pts]

    context.chain_proc { |chain|
      passwd = Etc.getpwnam(context.username)

      env = context.vars.fetch(:env, Hash.new)
      env['USER']  = passwd.name
      env['HOME']  = passwd.dir
      env['SHELL'] = passwd.shell

      program = [passwd.shell, passwd.shell.split('/').last.sub(/^/,'-')]

      args = Array.new

      options = Hash.new
      options[:unsetenv_others] = true
      options[:close_others] = true

      pid = fork do
        ptm.close
        Process.setsid
        Dir.chdir passwd.dir
        Process::GID.change_privilege passwd.gid
        Process::UID.change_privilege passwd.uid
        STDIN.reopen  pts, 'r'
        STDOUT.reopen pts, 'w'
        STDERR.reopen pts, 'w'
        pts.close
        exec env, program, *args, options
      end

      pts.close

      begin
        pid, status = Process.waitpid2 pid
        context.log_info { "shell exited with status #{status.inspect}" }
        status.exitstatus
      ensure
        unless status
          context.log_info { "exiting shell" }
          Process.kill :TERM, pid
          begin
            Timeout.timeout(1) do
              pid, status = Process.waitpid2 pid
            end
          rescue Timeout::Error
            context.log_warn { "force exiting shell" }
            Process.kill :KILL, pid
            pid, status = Process.waitpid2 pid
          end
          context.log_info { "shell exited with status #{status.inspect}" }
        end
      end
    }
  }
end