fixed small issues in CGod.class.php and remove old debug files
[PHP-P10.git] / Bots / CGod.class.php
1 <?php
2 /******************************* PHP-P10 v2 *****************************
3  * Copyright (C) 2011  Philipp Kreil (pk910)                            *
4  *                                                                      *
5  * This program is free software: you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation, either version 3 of the License, or    *
8  * (at your option) any later version.                                  *
9  *                                                                      * 
10  * This program is distributed in the hope that it will be useful,      *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
13  * GNU General Public License for more details.                         *
14  *                                                                      *
15  * You should have received a copy of the GNU General Public License    *
16  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17  *                                                                      *
18  ************************************************************************
19  * 
20  *  Bots/CGod.class.php
21  *
22  * simple C debugger...
23  *
24  */
25
26 class {$_NAME} extends Bot {
27         private $uplink;
28         private $c, $ccache = array();
29         
30         public function load($uplink, $old = false) {
31                 $this->uplink = $uplink;
32                 if(!$old) {
33                         $nick = "C";
34                         $ident = "c";
35                         $host = "Services.WebGamesNet.net";
36                         $ip = "0::0";
37                         $realname = "C C C C C";
38                         $modes = "ioknISD";
39                         $this->c = $this->uplink->addUser($nick,$ident,$host,$ip,$modes,$realname);
40                         if(is_a($this->c, "P10_User")) {
41                                 $this->uplink->join($this->c, "#c", (P10_Channel::USERPRIV_OPED | P10_Channel::USERPRIV_VOICE));
42                                 $this->uplink->join($this->c, "#dev", P10_Channel::USERPRIV_VOICE);
43                         }
44                 } else {
45                         $this->c = $old;
46                 }
47                 
48                 ModCMD::bind($this, BIND_CHANMSG, "recive_privmsg");
49                 ModCMD::bind($this, BIND_QUIT, "recive_quit");
50         }
51         
52         public function unload($rehash = false) {
53                 foreach($this->ccache as $id => $c) {
54                         fclose($c['pipes'][1]);
55                         fclose($c['pipes'][2]);
56                         proc_terminate($c['proc'],9);
57                 }
58                 $this->ccache = array();
59                 if($rehash) {
60                         return $this->c;
61                 } else {
62                         $this->uplink->delUser($this->c, "Bye.");
63                 }
64         }
65         
66         public function loop() {
67                 foreach($this->ccache as $id => $c) {
68                         if(!$this->checkstate($c)) {
69                 unlink("tmp/debug_".$c['id'].".c");
70                 unlink("tmp/debug_".$c['id']);
71                                 unset($this->ccache[$id]);
72                         }
73                 }
74         }
75         
76         function recive_privmsg($user, $channel, $message) {
77                 $opOnPHPChannel = false;
78                 $PHPChannel = P10_Channel::getChannelByName("#PHP");
79                 if($PHPChannel) {
80                         $privs = $PHPChannel->getUserPrivs($user);
81                         $opOnPHPChannel = ($privs & P10_Channel::USERPRIV_OPED);
82                 }
83                 if(!$user->getModes()->hasMode('o') && !$opOnPHPChannel) return 0;
84                 $exp=explode(" ", $message, 2);
85                 switch (strtolower($exp[0])) {
86                         case "~c":
87                                 if(count($this->ccache) > 5) {
88                                         $this->uplink->notice($this->c, $user, "too many running c processes at the moment!");
89                                         return;
90                                 }
91                                 $entry=array();
92                                 $entry['channel'] = $channel;
93                 $entry['id'] = rand(1, 999999);
94                 $fp = fopen("tmp/debug_".$entry['id'].".c", "w");
95                 fwrite($fp, "#include \"includes.h\"\n".$exp[1]);
96                 fclose($fp);
97                 $err = shell_exec("gcc -o tmp/debug_".$entry['id']." tmp/debug_".$entry['id'].".c 2>&1");
98                 if($err) {
99                     $err=str_replace("\r","",$err);
100                     $lines=explode("\n",$err);
101                     $i=0;
102                     foreach($lines as $line) {
103                         $i++;
104                         if($i>100) {
105                             $this->uplink->privmsg($this->c, $entry['channel'], "too many lines!");
106                             break; 
107                         }
108                         $this->uplink->privmsg($this->c, $entry['channel'], $line);
109                     }
110                 }
111                 if(!file_exists("tmp/debug_".$entry['id'])) {
112                     unlink("tmp/debug_".$entry['id'].".c");
113                     break;
114                 }
115                                 $descriptor = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("pipe", "w"));
116                                 $entry['proc'] = proc_open('tmp/debug_'.$entry['id'], $descriptor, $entry['pipes']);
117                                 if(!is_resource($entry['proc'])) {
118                                         $this->uplink->notice($this->c, $user, "error while loading c!");
119                                         return;
120                                 }
121                                 $entry['time'] = time();
122                                 fclose($entry['pipes'][0]);
123                                 $this->ccache[] = $entry;
124                                 break;
125                 }
126         }
127         
128         function recive_quit($user, $reason) {
129                 if($user === $this->c) {
130                         $this->load($this->uplink);
131                 }
132         }
133         
134         function checkstate($c) {
135                 $data = proc_get_status($c['proc']);
136                 if(!$data['running']) {
137                         $out="";
138                         while(!feof($c['pipes'][1])) {
139                                 $out .= fgets($c['pipes'][1], 128);
140                         }
141                         $eout="";
142                         while(!feof($c['pipes'][2])) {
143                                 $eout .= fgets($c['pipes'][2], 128);
144                         }
145                         if($out != "") {
146                                 $out=str_replace("\r","",$out);
147                                 $lines=explode("\n",$out);
148                                 $i=0;
149                                 foreach($lines as $line) {
150                                         $i++;
151                                         if($i>1000) {
152                                                 $this->uplink->privmsg($this->c, $c['channel'], "too many lines!");
153                                                 break; 
154                                         }
155                                         $this->uplink->privmsg($this->c, $c['channel'], $line);
156                                 }
157                         }
158                         if($eout != "") {
159                                 $eout=str_replace("\r","",$eout);
160                                 $lines=explode("\n",$eout);
161                                 $i=0;
162                                 foreach($lines as $line) {
163                                         $i++;
164                                         if($i>1000) { 
165                                                 $this->uplink->privmsg($this->c, $c['channel'], "too many lines!");
166                                                 break; 
167                                         }
168                                         $this->uplink->privmsg($this->c, $c['channel'], "\ 34".$line."\ 3");
169                                 }
170                         }
171                         fclose($c['pipes'][1]);
172                         fclose($c['pipes'][2]);
173                         proc_close($c['proc']);
174                         return false;
175                 } else {
176                         if($c['time']+10 > time()) {
177                                 return true;
178                         } else {
179                                 //TIMEOUT
180                                 if($c['term']) {
181                                         fclose($c['pipes'][1]);
182                                         fclose($c['pipes'][2]);
183                                         proc_terminate($c['proc'],9);
184                                         $this->uplink->privmsg($this->c, $c['channel'], "c hard timeout. sending SIGKILL");
185                                         return false;
186                                 } else {
187                                         proc_terminate($c['proc']);
188                                         $c['term']=true;
189                                         $this->uplink->privmsg($this->c, $c['channel'], "c timeout. (maximum of 10 seconds exceeded)  sending SIGTERM"); 
190                                         return true;
191                                 }
192                         }
193                 }
194         }
195         
196 }
197
198 ?>