1use strict;
2use warnings;
3
4use Test::More;
5use File::Spec;
6use Socket qw(AF_UNIX SOCK_STREAM PF_UNSPEC);
7
8sub sshd_cmd {
9    my $sc_name = 'sshd';
10
11    my @paths = qw( /usr
12                    /usr/local
13                    /usr/local/openssh
14                    /opt/ssh
15                    /opt/openssh );
16
17    @paths = map { ("$_/sbin/sshd", "$_/bin/sshd") } @paths;
18
19    for my $sshd (@paths) {
20	return $sshd if -x $sshd;
21    }
22}
23
24sub find_cmd {
25    my @path = qw(/usr/bin /bin
26		  /usr/local/bin
27		  /usr/sbin /sbin
28		  /opt/bin );
29
30    for my $cmd (@_) {
31	for my $path (@path) {
32	    my $r = "$path/$cmd";
33	    return $r if -x $r;
34	}
35    }
36    undef;
37}
38
39sub shell_is_clean {
40    my $shell = (getpwuid($>))[8];
41
42    socketpair my $up, my $down, AF_UNIX, SOCK_STREAM, PF_UNSPEC or return;
43    my $pid = fork;
44    unless ($pid) {
45        unless (defined $pid) {
46            diag "fork failed: $!";
47            return;
48        }
49        open STDIN,  '<&', $down;
50        open STDOUT, '>>&', $down;
51        open STDERR, '>>&', $down;
52
53        my $pid2 = fork;
54        if (defined $pid2 and not $pid2) {
55            setpgrp(0, 0);
56            # make bash read .bashrc on Debian systems:
57            delete $ENV{SHLVL};
58            $ENV{SSH_CLIENT} = "::1 12345 22";
59            do { exec $shell, '-c', 'echo ok' };
60        }
61        exit 0;
62    }
63    close $down;
64
65    my $out = do { local $/; <$up> };
66    if (!close($up) or $out ne "ok\n") {
67        diag "shell is not clean: \$?=$?, output...\n$out";
68        return;
69    }
70    1
71}
72
73my @last_open_fds;
74
75sub count_open_fds {
76    @last_open_fds = ();
77    if ($^O eq 'linux') {
78        if (opendir my $dh, "/proc/$$/fd") {
79            my $count = 0;
80            while (defined(my $fd = readdir $dh)) {
81                push @last_open_fds, $fd if $fd =~ /^\d+$/;
82            }
83            return scalar @last_open_fds;
84        }
85    }
86    ()
87}
88
89sub dump_open_fds {
90    my @ls = map { `ls -l /proc/$$/fd/$_ 2>&1` } @last_open_fds;
91    join('', "Currently open flle descriptors:\n", @ls);
92}
93
941;
95