1b39c5158Smillert#!./perl 2b39c5158Smillert 3b39c5158Smillertuse Config; 4de8cc8edSafresh1use IO::Socket; 5b39c5158Smillert 6b39c5158SmillertBEGIN { 7b39c5158Smillert my $reason; 8de8cc8edSafresh1 my $can_fork = $Config{d_fork} || 9de8cc8edSafresh1 (($^O eq 'MSWin32' || $^O eq 'NetWare') and 10de8cc8edSafresh1 $Config{useithreads} and 11de8cc8edSafresh1 $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/ 12de8cc8edSafresh1 ); 13de8cc8edSafresh1 14b39c5158Smillert if ($ENV{PERL_CORE} and $Config{'extensions'} !~ /\bSocket\b/) { 15b39c5158Smillert $reason = 'Socket extension unavailable'; 16b39c5158Smillert } 17b39c5158Smillert elsif ($ENV{PERL_CORE} and $Config{'extensions'} !~ /\bIO\b/) { 18b39c5158Smillert $reason = 'IO extension unavailable'; 19b39c5158Smillert } 20b39c5158Smillert elsif ($^O eq 'os2') { 21b39c5158Smillert eval {IO::Socket::pack_sockaddr_un('/foo/bar') || 1} 22b39c5158Smillert or $@ !~ /not implemented/ or 23b39c5158Smillert $reason = 'compiled without TCP/IP stack v4'; 24b39c5158Smillert } 25de8cc8edSafresh1 elsif ($^O =~ m/^(?:qnx|nto|vos)$/ ) { 26b39c5158Smillert $reason = "UNIX domain sockets not implemented on $^O"; 27b39c5158Smillert } 28de8cc8edSafresh1 elsif (! $can_fork) { 29b39c5158Smillert $reason = 'no fork'; 30b39c5158Smillert } 31de8cc8edSafresh1 elsif ($^O eq 'MSWin32') { 32de8cc8edSafresh1 if ($ENV{CONTINUOUS_INTEGRATION}) { 33de8cc8edSafresh1 $reason = 'Skipping on Windows CI, see gh17575 and gh17429'; 34de8cc8edSafresh1 } else { 35de8cc8edSafresh1 $reason = "AF_UNIX unavailable or disabled on this platform" 36de8cc8edSafresh1 unless eval { socket(my $sock, PF_UNIX, SOCK_STREAM, 0) }; 37de8cc8edSafresh1 } 38de8cc8edSafresh1 } 39de8cc8edSafresh1 40b39c5158Smillert if ($reason) { 41b39c5158Smillert print "1..0 # Skip: $reason\n"; 42b39c5158Smillert exit 0; 43b39c5158Smillert } 44b39c5158Smillert} 45b39c5158Smillert 46*256a93a4Safresh1my $PATH = "sock-$$"; 47b39c5158Smillert 48b39c5158Smillertif ($^O eq 'os2') { # Can't create sockets with relative path... 49b39c5158Smillert require Cwd; 50b39c5158Smillert my $d = Cwd::cwd(); 51b39c5158Smillert $d =~ s/^[a-z]://i; 52b39c5158Smillert $PATH = "$d/$PATH"; 53b39c5158Smillert} 54b39c5158Smillert 55b39c5158Smillert# Test if we can create the file within the tmp directory 565759b3d2Safresh1if (-e $PATH or not open(TEST, '>', $PATH) and $^O ne 'os2') { 57b39c5158Smillert print "1..0 # Skip: cannot open '$PATH' for write\n"; 58b39c5158Smillert exit 0; 59b39c5158Smillert} 60b39c5158Smillertclose(TEST); 61b39c5158Smillertunlink($PATH) or $^O eq 'os2' or die "Can't unlink $PATH: $!"; 62b39c5158Smillert 63b39c5158Smillert# Start testing 64b39c5158Smillert$| = 1; 65b39c5158Smillertprint "1..5\n"; 66b39c5158Smillert 67*256a93a4Safresh1my $listen = IO::Socket::UNIX->new(Local => $PATH, Listen => 0); 68b39c5158Smillert 69b39c5158Smillert# Sometimes UNIX filesystems are mounted for security reasons 70b39c5158Smillert# with "nodev" option which spells out "no" for creating UNIX 71b39c5158Smillert# local sockets. Therefore we will retry with a File::Temp 72b39c5158Smillert# generated filename from a temp directory. 73b39c5158Smillertunless (defined $listen) { 74b39c5158Smillert eval { require File::Temp }; 75b39c5158Smillert unless ($@) { 76*256a93a4Safresh1 File::Temp->import( 'mktemp' ); 77b39c5158Smillert for my $TMPDIR ($ENV{TMPDIR}, "/tmp") { 78b39c5158Smillert if (defined $TMPDIR && -d $TMPDIR && -w $TMPDIR) { 79b39c5158Smillert $PATH = mktemp("$TMPDIR/sXXXXXXXX"); 80b39c5158Smillert last if $listen = IO::Socket::UNIX->new(Local => $PATH, 81b39c5158Smillert Listen => 0); 82b39c5158Smillert } 83b39c5158Smillert } 84b39c5158Smillert } 85b39c5158Smillert defined $listen or die "$PATH: $!"; 86b39c5158Smillert} 87b39c5158Smillertprint "ok 1\n"; 88b39c5158Smillert 89*256a93a4Safresh1if (my $pid = fork()) { 90b39c5158Smillert 91*256a93a4Safresh1 my $sock = $listen->accept(); 92b39c5158Smillert 93b39c5158Smillert if (defined $sock) { 94b39c5158Smillert print "ok 2\n"; 95b39c5158Smillert 96b39c5158Smillert print $sock->getline(); 97b39c5158Smillert 98b39c5158Smillert print $sock "ok 4\n"; 99b39c5158Smillert 100b39c5158Smillert $sock->close; 101b39c5158Smillert 102b39c5158Smillert waitpid($pid,0); 103b39c5158Smillert unlink($PATH) || $^O eq 'os2' || warn "Can't unlink $PATH: $!"; 104b39c5158Smillert 105b39c5158Smillert print "ok 5\n"; 106b39c5158Smillert } else { 107b39c5158Smillert print "# accept() failed: $!\n"; 108b39c5158Smillert for (2..5) { 109b39c5158Smillert print "not ok $_ # accept failed\n"; 110b39c5158Smillert } 111b39c5158Smillert } 112b39c5158Smillert} elsif(defined $pid) { 113b39c5158Smillert 114*256a93a4Safresh1 my $sock = IO::Socket::UNIX->new(Peer => $PATH) or die "$!"; 115b39c5158Smillert 116b39c5158Smillert print $sock "ok 3\n"; 117b39c5158Smillert 118b39c5158Smillert print $sock->getline(); 119b39c5158Smillert 120b39c5158Smillert $sock->close; 121b39c5158Smillert 122b39c5158Smillert exit; 123b39c5158Smillert} else { 124b39c5158Smillert die; 125b39c5158Smillert} 126