1
2
3
4
5
6
7
8
9
10
11
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/perl

use FCGI;
#perl -MCPAN -e 'install FCGI'
use Socket;
use POSIX qw(setsid);
#use Fcntl;

require 'syscall.ph';

#&daemonize;

#this keeps the program alive or something after exec'ing perl scripts
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=" . shift() . "\n"; };
eval q{exit};

if($@) {
    exit unless $@ =~ /^fakeexit/;
}

&main;

#sub daemonize() {
#    chdir '/'                 or die "Can't chdir to /: $!";
#    defined(my $pid = fork)   or die "Can't fork: $!";
#    exit if $pid;
#    setsid                    or die "Can't start a new session: $!";
#    umask 0;
#}

sub main {
    # use IP sockets
    #$socket = FCGI::OpenSocket("127.0.0.1:8999", 10);

    # use UNIX sockets - user running this script must have w access to the 'nginx' folder!!
    #$socket = FCGI::OpenSocket("/var/run/nginx/perl_cgi-dispatch.sock", 10);
    
    $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%req_params);

    if($request) {
        request_loop();
    }
    #FCGI::CloseSocket( $socket );
}

sub hello {
    print("Content-type: text/plain\r\n\r\n");
    print "here!";
} 

sub request_loop {
    while($request->Accept() >= 0) {

        # processing any STDIN input from WebServer (for CGI-POST actions)
        $stdin_passthrough ='';
        $req_len = 0 + $req_params{'CONTENT_LENGTH'};
        if( ($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ) {
            my $bytes_read = 0;
            while($bytes_read < $req_len) {
                my $data = '';
                my $bytes = read(STDIN, $data, ($req_len - $bytes_read));
                last if($bytes == 0 || !defined($bytes));
                $stdin_passthrough .= $data;
                $bytes_read += $bytes;
            }
        }

        #running the cgi app
        if((-x $req_params{SCRIPT_FILENAME}) && # can I execute this?
           (-s $req_params{SCRIPT_FILENAME}) && # Is this file empty?
           (-r $req_params{SCRIPT_FILENAME})) { # can I read this file?
            pipe(CHILD_RD, PARENT_WR);
            my $pid = open(KID_TO_READ, "-|");

            unless(defined($pid)) {
                print("Content-type: text/plain\r\n\r\n");
                print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";
                next;
            }

            if($pid > 0) {
                close(CHILD_RD);
                print PARENT_WR $stdin_passthrough;
                close(PARENT_WR);

                while(my $s = <KID_TO_READ>) { print $s; }
                close KID_TO_READ;
                waitpid($pid, 0);
            }
            else {
                foreach $key (keys %req_params) {
                    $ENV{$key} = $req_params{$key};
                }

                # cd to the script's local directory
                if($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) {
                    chdir $1;
                }

                close(PARENT_WR);
                close(STDIN);
                #fcntl(CHILD_RD, F_DUPFD, 0);
                syscall(&SYS_dup2, fileno(CHILD_RD), 0);
                #open(STDIN, "<&CHILD_RD");
                exec($req_params{SCRIPT_FILENAME});
                die("exec failed");
            }
        }
        else {
            print("Content-type: text/plain\r\n\r\n");
            print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";
        }
    }
}