]> gitweb.pimeys.fr Git - bots/hung.git/blob - hung.py
.gitignore += *.out
[bots/hung.git] / hung.py
1 #!/usr/bin/python
2 # -*- coding:utf8 -*-
3
4 # Codé par 20-100 le 23/04/12
5
6 # Un bot IRC qui joue au pendu
7
8 import threading
9 import random
10 import time
11 import socket, ssl, json
12 import pickle
13 import re
14 import os
15 import signal
16 import sys
17 from commands import getstatusoutput as ex
18
19 # Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP
20 sys.path.insert(0, "/home/vincent/scripts/python-myirclib")
21 import irclib
22 import ircbot
23
24 import sys
25
26 # Fichier de conf
27 import config
28
29 def get_config_logfile(serveur):
30 serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans","localhost":"localhost"}
31 return config.logfile_template%(serveurs[serveur])
32
33 def log(serveur,channel,auteur=None,message=None):
34 f=open(get_config_logfile(serveur),"a")
35 if auteur==message==None:
36 # alors c'est que c'est pas un channel mais juste une ligne de log
37 chain="%s %s"%(time.strftime("%F %T"),channel)
38 else:
39 chain="%s [%s:%s] %s"%(time.strftime("%F %T"),channel,auteur,message)
40 f.write(chain+"\n")
41 if config.debug_stdout:
42 print chain
43 f.close()
44
45
46 class UnicodeBotError(Exception):
47 pass
48 def bot_unicode(chain):
49 try:
50 unicode(chain,"utf8")
51 except UnicodeDecodeError as exc:
52 raise UnicodeBotError
53
54 def remplace_accents(chaine):
55 chaine=chaine.lower()
56 remplacements = {u"á":u"a",u"à":u"a",u"â":u"a",u"ä":u"a",u"é":u"e",u"è":u"e",u"ê":u"e",u"ë":u"e",u"í":u"i",u"ì":u"i",u"î":u"i",u"ï":u"i",u"ó":u"o", u"ò":u"o",u"ô":u"o",u"ö":u"o",u"ú":u"u",u"ù":u"u",u"û":u"u",u"ü":u"u",u"ý":u"y",u"ỳ":u"y",u"ŷ":u"y",u"ÿ":u"y",u"œ":u"oe",u"æ":u"ae"}
57 for avant,apres in remplacements.items():
58 chaine=chaine.replace(avant,apres)
59 return chaine
60
61 def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
62 if case_sensitive:
63 chain=unicode(chain,"utf8")
64 else:
65 chain=unicode(chain,"utf8").lower()
66 allmatches="("+"|".join(matches)+")"
67 reg=(avant+allmatches+apres).lower()
68 o=re.match(reg,chain)
69 return o
70
71 def is_tag(chain):
72 return is_something(chain,config.tag_triggers)
73
74 def is_mot(mot,liste):
75 real_word = "".join([lettre[0] for lettre in liste])
76 real_word = real_word.decode("utf8").lower()
77 mot=remplace_accents(mot.decode("utf8"))
78 return mot==real_word
79
80 class Hung(ircbot.SingleServerIRCBot):
81 def __init__(self,serveur,debug=False):
82 temporary_pseudo=config.irc_pseudo+str(random.randrange(10000,100000))
83 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
84 temporary_pseudo,"Bot irc pour jouer au pendu", 10)
85 self.debug=debug
86 self.serveur=serveur
87 self.overops=config.overops
88 self.ops=self.overops+config.ops
89 self.report_bugs_to=config.report_bugs_to
90 self.chanlist=config.chanlist
91 self.stay_channels=config.stay_channels
92 self.play_channels=config.play_channels
93 self.play_status={i:[None,None,None] for i in self.play_channels}
94 self.quiet_channels=config.quiet_channels
95
96
97 def give_me_my_pseudo(self,serv):
98 serv.privmsg("NickServ","RECOVER %s %s"%(config.irc_pseudo,config.irc_password))
99 serv.privmsg("NickServ","RELEASE %s %s"%(config.irc_pseudo,config.irc_password))
100 time.sleep(0.3)
101 serv.nick(config.irc_pseudo)
102
103 def on_welcome(self, serv, ev):
104 self.serv=serv # ça serv ira :)
105 self.give_me_my_pseudo(serv)
106 serv.privmsg("NickServ","IDENTIFY %s"%(config.irc_password))
107 log(self.serveur,"Connected")
108 if self.debug:
109 self.chanlist=["#bot"]
110 self.play_channels=["#bot"]
111 for c in self.chanlist:
112 log(self.serveur,"JOIN %s"%(c))
113 serv.join(c)
114
115 def pourmoi(self, serv, message):
116 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
117 pseudo=serv.get_nickname()
118 size=len(pseudo)
119 if message[:size]==pseudo and len(message)>size and message[size]==":":
120 return (True,message[size+1:].lstrip(" "))
121 else:
122 return (False,message)
123
124 def on_privmsg(self, serv, ev):
125 message=ev.arguments()[0]
126 auteur = irclib.nm_to_n(ev.source())
127 try:
128 test=bot_unicode(message)
129 except UnicodeBotError:
130 if config.utf8_trigger:
131 serv.privmsg(auteur, config.utf8_fail_answers)
132 return
133 message=message.split()
134 cmd=message[0].lower()
135 notunderstood=False
136 if cmd=="help":
137 helpmsg_default="""Liste des commandes :
138 HELP Affiche ce message d'aide
139 SCORE Affiche ton score
140 SCORES Affiche les scores"""
141 helpmsg_ops="""
142 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
143 LEAVE Faire quitter un channel
144 PLAY Passe un channel en mode "jouer"
145 NOPLAY Passe un channel en mode "ne pas jouer"
146 QUIET Se taire sur un channel
147 NOQUIET Opposé de QUIET
148 RELOAD Recharge la config"""
149 helpmsg_overops="""
150 SAY Fais envoyer un message sur un chan ou à une personne
151 DO Me fait faire une action sur un chan
152 STAY Ignorera les prochains LEAVE pour un chan
153 NOSTAY Opposé de STAY
154 STATUS Montre l'état courant
155 DIE Mourir"""
156 helpmsg=helpmsg_default
157 if auteur in self.ops:
158 helpmsg+=helpmsg_ops
159 if auteur in self.overops:
160 helpmsg+=helpmsg_overops
161 for ligne in helpmsg.split("\n"):
162 serv.privmsg(auteur,ligne)
163 elif cmd=="join":
164 if auteur in self.ops:
165 if len(message)>1:
166 if message[1] in self.chanlist:
167 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
168 else:
169 serv.join(message[1])
170 self.chanlist.append(message[1])
171 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
172 log(self.serveur,"priv",auteur," ".join(message))
173 else:
174 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
175 else:
176 notunderstood=True
177 elif cmd=="leave":
178 if auteur in self.ops and len(message)>1:
179 if message[1] in self.chanlist:
180 if not (message[1] in self.stay_channels) or auteur in self.overops:
181 self.quitter(message[1]," ".join(message[2:]))
182 self.chanlist.remove(message[1])
183 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
184 else:
185 serv.privmsg(auteur,"Non, je reste !")
186 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
187 else:
188 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
189 else:
190 notunderstood=True
191 elif cmd=="play":
192 if auteur in self.ops:
193 if len(message)>1:
194 if message[1] in self.play_channels:
195 serv.privmsg(auteur,"Je play déjà sur %s."%(message[1]))
196 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
197 else:
198 self.play_channels.append(message[1])
199 self.play_status[message[1]]=[None,None,None]
200 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
201 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
202 else:
203 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
204 else:
205 notunderstood=True
206 elif cmd=="noplay":
207 if auteur in self.ops:
208 if len(message)>1:
209 if message[1] in self.play_channels:
210 self.play_channels.remove(message[1])
211 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
212 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
213 else:
214 serv.privmsg(auteur,"Je ne play pas sur %s."%(message[1]))
215 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
216 else:
217 notunderstood=True
218 elif cmd=="stay":
219 if auteur in self.overops:
220 if len(message)>1:
221 if message[1] in self.stay_channels:
222 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
223 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
224 else:
225 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
226 self.stay_channels.append(message[1])
227 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
228 else:
229 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
230 else:
231 notunderstood=True
232 elif cmd=="nostay":
233 if auteur in self.overops:
234 if len(message)>1:
235 if message[1] in self.stay_channels:
236 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
237 self.stay_channels.remove(message[1])
238 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
239 else:
240 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
241 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
242
243 else:
244 notunderstood=True
245 elif cmd in ["states","status"]:
246 if auteur in self.overops:
247 for k in self.play_status.keys():
248 if self.play_status[k]==[None,None,None]:
249 serv.privmsg(auteur,"None")
250 else:
251 serv.privmsg(auteur,"%s : %s (%s) [%s]"%(k,"".join([str(i[0]) for i in self.play_status[k][0]])
252 ,self.play_status[k][1], self.play_status[k][2]))
253 elif cmd=="die":
254 if auteur in self.overops:
255 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
256 self.mourir()
257 else:
258 notunderstood=True
259 elif cmd=="quiet":
260 if auteur in self.ops:
261 if len(message)>1:
262 if message[1] in self.quiet_channels:
263 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
264 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
265 else:
266 self.quiet_channels.append(message[1])
267 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
268 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
269 else:
270 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
271 else:
272 notunderstood=True
273 elif cmd=="noquiet":
274 if auteur in self.ops:
275 if len(message)>1:
276 if message[1] in self.quiet_channels:
277 self.quiet_channels.remove(message[1])
278 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
279 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
280 else:
281 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
282 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
283 else:
284 notunderstood=True
285 elif cmd=="reload":
286 if auteur in self.ops:
287 self.reload(auteur)
288 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
289 else:
290 notunderstood=True
291 elif cmd=="say":
292 if auteur in self.overops and len(message)>2:
293 serv.privmsg(message[1]," ".join(message[2:]))
294 log(self.serveur,"priv",auteur," ".join(message))
295 elif len(message)<=2:
296 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
297 else:
298 notunderstood=True
299 elif cmd=="do":
300 if auteur in self.overops and len(message)>2:
301 serv.action(message[1]," ".join(message[2:]))
302 log(self.serveur,"priv",auteur," ".join(message))
303 elif len(message)<=2:
304 serv.privmsg(auteur,"Syntaxe : DO <channel> <action>")
305 else:
306 notunderstood=True
307 elif cmd in ["score","scores"]:
308 self.send_scores(serv,auteur)
309 else:
310 notunderstood=True
311 if notunderstood:
312 serv.privmsg(auteur,"Je n'ai pas compris. Essaye HELP…")
313
314 def affiche_mot(self, serv, canal, begin="Mot courant"):
315 if self.play_status.has_key(canal):
316 mot = self.play_status[canal][0]
317 obfuskated=" ".join([lettre[0] if lettre[1] else "_" for lettre in mot])
318 serv.privmsg(canal,"%s : %s"%(begin,obfuskated))
319
320 def start_partie(self, serv, canal):
321 mots=[mot.strip() for mot in open(config.dico_mots).readlines()]
322 defs=[defi.strip() for defi in open(config.dico_defs).readlines()]
323 indice = random.randrange(0,len(mots))
324 mot,definition=mots[indice],defs[indice]
325 # ' et - sont considérés comme déjà devinés
326 mot = [(lettre,lettre in "'-()") for lettre in list(mot)]
327 self.play_status[canal]=[mot,definition,{}]
328 self.affiche_mot(serv, canal, begin="Devinez")
329
330 def on_pubmsg(self, serv, ev):
331 auteur = irclib.nm_to_n(ev.source())
332 canal = ev.target()
333 message = ev.arguments()[0]
334 try:
335 test=bot_unicode(message)
336 except UnicodeBotError:
337 if not canal in self.quiet_channels and config.utf8_trigger:
338 serv.privmsg(canal, "%s: %s"%(auteur,config.utf8_fail_answers))
339 return
340 pour_moi,message=self.pourmoi(serv,message)
341 if pour_moi and message.split()!=[]:
342 cmd=message.split()[0].lower()
343 try:
344 args=" ".join(message.split()[1:])
345 except:
346 args=""
347 if cmd in ["meurs","die","crève"]:
348 if auteur in self.overops:
349 log(self.serveur,canal,auteur,message+"[successful]")
350 self.mourir()
351 else:
352 serv.privmsg(canal,"%s: crève !"%(auteur))
353 log(self.serveur,canal,auteur,message+"[failed]")
354 elif cmd == "reload":
355 if auteur in self.ops:
356 log(self.serveur, canal, auteur, message+"[successful]")
357 self.reload(canal)
358 elif cmd in ["part","leave","dégage"]:
359 if auteur in self.ops and (not (canal in self.stay_channels)
360 or auteur in self.overops):
361 self.quitter(canal)
362 log(self.serveur,canal,auteur,message+"[successful]")
363 if canal in self.chanlist:
364 self.chanlist.remove(canal)
365 else:
366 serv.privmsg(canal,"%s: Non, je reste !"%(auteur))
367 log(self.serveur,canal,auteur,message+"[failed]")
368 elif cmd in ["play","jeu","encore","again","partie","pendu","game","mot","go","allez"]:
369 if not canal in self.quiet_channels and canal in self.play_channels:
370 if self.play_status.has_key(canal):
371 if self.play_status[canal]==[None,None,None]:
372 self.start_partie(serv, canal)
373 else:
374 self.affiche_mot(serv, canal, begin="%s: Rappel"%(auteur))
375 else:
376 self.play_status[canal]=[None,None,None]
377 self.start_partie(serv, canal)
378 elif not canal in self.play_channels:
379 serv.privmsg(canal,"%s: pas ici…"%(auteur))
380 elif (cmd in list("azertyuiopqsdfghjklmwxcvbn") and canal in self.play_channels
381 and self.play_status.has_key(canal) and self.play_status[canal]!=[None,None,None]):
382 giv_let=cmd.upper()
383 liste=self.play_status[canal][0]
384 listeapres=[(lettre[0],lettre[1] or lettre[0]==giv_let) for lettre in liste]
385 if liste!=listeapres:
386 nbtrouvees=(sum([lettre[1] for lettre in listeapres if not lettre[0] in "'-()"])
387 - sum([lettre[1] for lettre in liste if not lettre[0] in "'-()"]))
388 if self.play_status[canal][2].has_key(auteur):
389 self.play_status[canal][2][auteur]+= nbtrouvees
390 else:
391 self.play_status[canal][2][auteur] = nbtrouvees
392 self.play_status[canal][0]=listeapres
393 self.affiche_mot(serv, canal, begin="%s placé"%(giv_let))
394 if all([lettre[1] for lettre in listeapres]):
395 self.gagne(serv, canal)
396
397 elif cmd in ["score","scores","!score","!scores"]:
398 self.send_scores(serv,auteur)
399 if cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
400 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
401 if is_tag(message) and not canal in self.quiet_channels:
402 if auteur in self.ops:
403 action=random.choice(config.tag_actions)
404 serv.action(canal,action.encode("utf8"))
405 self.quiet_channels.append(canal)
406 else:
407 answer=random.choice(config.tag_answers)
408 for ligne in answer.split("\n"):
409 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
410 # on essaye de voir si le mot fourni matche la partie en cours
411 mot = cmd
412 if self.play_status[canal][0]!=None and is_mot(mot, self.play_status[canal][0]):
413 # on a trouvé le mot
414 # on regarde combien de lettre il manquait
415 manquait = sum([not lettre[1] for lettre in self.play_status[canal][0]])
416 self.add_score({auteur: manquait})
417 if self.play_status[canal][2].has_key(auteur):
418 self.play_status[canal][2][auteur]+=manquait
419 else:
420 self.play_status[canal][2][auteur]=manquait
421 self.gagne(serv, canal, bonus=auteur, bonusvalue=manquait)
422 else:
423 pass
424
425
426 def on_action(self, serv, ev):
427 action = ev.arguments()[0]
428 auteur = irclib.nm_to_n(ev.source())
429 channel = ev.target()
430
431
432 def on_kick(self,serv,ev):
433 auteur = irclib.nm_to_n(ev.source())
434 channel = ev.target()
435 victime = ev.arguments()[0]
436 raison = ev.arguments()[1]
437 if victime==self.nick:
438 log(self.serveur,"%s kické de %s par %s (raison : %s)" %(victime,channel,auteur,raison))
439 time.sleep(5)
440 serv.join(channel)
441 # on ne dit rien au rejoin
442 #l1,l2=config.kick_answers,config.kick_actions
443 #n1,n2=len(l1),len(l2)
444 #i=random.randrange(n1+n2)
445 #if i>=n1:
446 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
447 #else:
448 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
449
450 def _getnick(self):
451 return self.serv.get_nickname()
452 nick = property(_getnick)
453
454 def quitter(self,chan,leave_message=None):
455 if leave_message==None:
456 leave_message=random.choice(config.leave_messages)
457 self.serv.part(chan,message=leave_message.encode("utf8"))
458
459 def mourir(self):
460 quit_message=random.choice(config.quit_messages)
461 self.die(msg=quit_message.encode("utf8"))
462
463 def get_scores(self):
464 f=open(config.scores_file)
465 scores=pickle.load(f)
466 f.close()
467 return scores
468 def save_scores(self,scores):
469 f=open(config.scores_file,'w')
470 pickle.dump(scores,f)
471 f.close()
472 def add_score(self,dico):
473 scores=self.get_scores()
474 for k,v in dico.items():
475 if scores.has_key(k):
476 scores[k]+=v
477 else:
478 scores[k]=v
479 self.save_scores(scores)
480 def send_scores(self, serv, destinataire):
481 scores=self.get_scores()
482 scores=scores.items()
483 scores.sort(lambda x,y:cmp(x[1],y[1]))
484 scores.reverse()
485 serv.privmsg(destinataire,"Scores by score : "+" ; ".join(["%s %s"%(k,v) for (k,v) in scores]) )
486 scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
487 serv.privmsg(destinataire,"Scores by pseudo : "+" ; ".join(["%s %s"%(k,v) for (k,v) in scores]) )
488
489 def gagne(self, serv, canal, bonus=None, bonusvalue=2):
490 realword="".join([lettre[0] for lettre in self.play_status[canal][0]])
491 definition = self.play_status[canal][1]
492 serv.privmsg(canal,"Bravo ! C'était %s"%(realword))
493 serv.privmsg(canal,definition)
494 nlettre=float(len(realword.replace("'","").replace("-","")))
495 contribs=["%s:%s%%%s"%(pseudo,str(int(100*contrib/nlettre)),("+bonus(%s)"%(bonusvalue))*(bonus==pseudo)) for pseudo,contrib in self.play_status[canal][2].items()]
496 contribs_score={pseudo:int(10*contrib/nlettre) for pseudo,contrib in self.play_status[canal][2].items()}
497 self.add_score(contribs_score)
498 serv.privmsg(canal,"Contributions : %s"%(" ".join(contribs)) )
499 self.play_status[canal]=[None,None,None]
500
501 def reload(self, auteur=None):
502 reload(config)
503 if auteur in [None, "SIGHUP"]:
504 towrite = "Config reloaded" + " (SIGHUP received)"*(auteur == "SIGHUP")
505 for to in config.report_bugs_to:
506 self.serv.privmsg(to, towrite)
507 log(self.serveur, towrite)
508 else:
509 self.serv.privmsg(auteur,"Config reloaded")
510
511 def start_as_daemon(self, outfile):
512 sys.stderr = Logger(outfile)
513 self.start()
514
515
516 class Logger(object):
517 """Pour écrire ailleurs que sur stdout"""
518 def __init__(self, filename="hung.full.log"):
519 self.filename = filename
520
521 def write(self, message):
522 f = open(self.filename, "a")
523 f.write(message)
524 f.close()
525
526
527 if __name__=="__main__":
528 import sys
529 if len(sys.argv)==1:
530 print "Usage : hung.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
531 print " --outfile sans --no-output ni --daemon n'a aucun effet"
532 exit(1)
533 serveur=sys.argv[1]
534 if "--daemon" in sys.argv:
535 thisfile = os.path.realpath(__file__)
536 thisdirectory = thisfile.rsplit("/", 1)[0]
537 os.chdir(thisdirectory)
538 daemon = True
539 else:
540 daemon = False
541 if "debug" in sys.argv or "--debug" in sys.argv:
542 debug=True
543 else:
544 debug=False
545 if "--no-output" in sys.argv or "--daemon" in sys.argv:
546 outfile = "/var/log/bots/hung.full.log"
547 for arg in sys.argv:
548 arg = arg.split("=")
549 if arg[0].strip('-') in ["out", "outfile", "logfile"]:
550 outfile = arg[1]
551 sys.stdout = Logger(outfile)
552 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
553 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org",
554 "localhost":"localhost"}
555 try:
556 serveur=serveurs[serveur]
557 except KeyError:
558 print "Server Unknown : %s"%(serveur)
559 exit(404)
560 hung=Hung(serveur,debug)
561 # Si on reçoit un SIGHUP, on reload la config
562 def sighup_handler(signum, frame):
563 hung.reload("SIGHUP")
564 signal.signal(signal.SIGHUP, sighup_handler)
565 if daemon:
566 child_pid = os.fork()
567 if child_pid == 0:
568 os.setsid()
569 hung.start_as_daemon(outfile)
570 else:
571 # on enregistre le pid de hung
572 pidfile = "/var/run/bots/hung.pid"
573 for arg in sys.argv:
574 arg = arg.split("=")
575 if arg[0].strip('-') in ["pidfile"]:
576 pidfile = arg[1]
577 f = open(pidfile, "w")
578 f.write("%s\n" % child_pid)
579 f.close()
580 else:
581 hung.start()
582