1 |
commit: 12b34e7369e0c0561da1af0a81ca588f5a026e0d |
2 |
Author: Alexander Bersenev <bay <AT> hackerdom <DOT> ru> |
3 |
AuthorDate: Sat Jul 2 16:28:32 2011 +0000 |
4 |
Commit: Александр Берсенев <bay <AT> hackerdom <DOT> ru> |
5 |
CommitDate: Sat Jul 2 16:28:32 2011 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/autodep.git;a=commit;h=12b34e73 |
7 |
|
8 |
ctrl-c handling |
9 |
|
10 |
--- |
11 |
logger/src/autodep/logfs/fstracer.py | 219 ++++++++++++++-------------- |
12 |
logger/src/autodep/logfs/logger_fusefs.py | 15 ++- |
13 |
logger/src/autodep/logfs/logger_hooklib.py | 1 + |
14 |
logger/src/autodep/showfsevents.py | 8 +- |
15 |
4 files changed, 127 insertions(+), 116 deletions(-) |
16 |
|
17 |
diff --git a/logger/src/autodep/logfs/fstracer.py b/logger/src/autodep/logfs/fstracer.py |
18 |
index 1b99f8e..80666e6 100644 |
19 |
--- a/logger/src/autodep/logfs/fstracer.py |
20 |
+++ b/logger/src/autodep/logfs/fstracer.py |
21 |
@@ -11,12 +11,16 @@ import tempfile |
22 |
import socket |
23 |
import select |
24 |
import re |
25 |
+import signal |
26 |
|
27 |
import proc_helpers |
28 |
|
29 |
import logger_hooklib |
30 |
import logger_fusefs |
31 |
|
32 |
+stop=False; |
33 |
+stoptime=0; |
34 |
+ |
35 |
def parse_message(message): |
36 |
ret=message.split("\0") |
37 |
return ret |
38 |
@@ -92,27 +96,6 @@ def checkparent(parent,child): |
39 |
print "External actions with filesystem detected pid of external prog is %d" % child |
40 |
return False |
41 |
|
42 |
-# check pid, returns stage of building |
43 |
-def get_stage_by_pid(pid,toppid): |
44 |
- #return "unknown" |
45 |
- |
46 |
- currpid=proc_helpers.getparentpid(pid) |
47 |
- try: |
48 |
- while currpid>1 and currpid!=toppid: |
49 |
- cmdlinefile=open("/proc/%d/cmdline" % currpid,"r") |
50 |
- cmdline=cmdlinefile.read() |
51 |
- cmdlinefile.close() |
52 |
- arguments=cmdline.split("\0") |
53 |
- #print arguments |
54 |
- if len(arguments)>=3 and arguments[1][-9:]=="ebuild.sh": |
55 |
- return arguments[2] |
56 |
- currpid=proc_helpers.getparentpid(currpid) |
57 |
- |
58 |
- |
59 |
- except IOError,e: |
60 |
- return "unknown" |
61 |
- |
62 |
- return "unknown" |
63 |
|
64 |
# default access filter. Allow acess to all files |
65 |
def defaultfilter(eventname, filename, pid): |
66 |
@@ -127,7 +110,6 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter) |
67 |
socketname = os.path.join(tmpdir, 'socket') |
68 |
|
69 |
try: |
70 |
- #sock_listen=socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
71 |
sock_listen=socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) |
72 |
|
73 |
sock_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
74 |
@@ -142,7 +124,6 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter) |
75 |
return [] |
76 |
else: |
77 |
#print socketname |
78 |
- |
79 |
pid=os.fork() |
80 |
if pid==0: |
81 |
logger=None |
82 |
@@ -160,100 +141,116 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter) |
83 |
print "Launch likely was unsuccessful" |
84 |
sys.exit(1) |
85 |
else: |
86 |
+ def signal_handler(sig, frame): |
87 |
+ print "You pressed Ctrl+C!" |
88 |
+ global stoptime |
89 |
+ if(time.time()-stoptime>5): |
90 |
+ print "Sending SIGINT to child" |
91 |
+ print "Press again in 5 seconds to force exit" |
92 |
+ stoptime=time.time() |
93 |
+ else: |
94 |
+ print "Sending SIGKILL to child" |
95 |
+ os.kill(pid,signal.SIGKILL) |
96 |
+ os._exit(1) |
97 |
+ global signal |
98 |
+ signal.signal(signal.SIGINT, signal_handler) |
99 |
+ |
100 |
epoll=select.epoll() |
101 |
epoll.register(sock_listen.fileno(), select.EPOLLIN) |
102 |
|
103 |
connects = 0; |
104 |
clients={} |
105 |
- stop=0 |
106 |
was_first_connect=False |
107 |
- |
108 |
- #print "fileno listen: %d",sock_listen.fileno() |
109 |
- |
110 |
- while stop==0: |
111 |
- sock_events = epoll.poll(3) |
112 |
- for fileno, sock_event in sock_events: |
113 |
- if fileno == sock_listen.fileno(): |
114 |
- #print "\n\nEVENT\n\n" |
115 |
- ret = sock_listen.accept() |
116 |
- #print ret |
117 |
- if ret is None: |
118 |
- # print "\n\nPASS\n\n" |
119 |
- pass |
120 |
- else: |
121 |
- (client,addr)=ret |
122 |
- # print client |
123 |
- connects+=1; # client accepted |
124 |
- was_first_connect=True |
125 |
- epoll.register(client.fileno(), select.EPOLLIN) |
126 |
- clients[client.fileno()]=client |
127 |
- #print "opened %d" % client.fileno() |
128 |
- #elif sock_event & select.EPOLLHUP: |
129 |
- #epoll.unregister(fileno) |
130 |
- #clients[fileno].close() |
131 |
- #del clients[fileno] |
132 |
- #connects-=1 |
133 |
- |
134 |
- elif sock_event & select.EPOLLIN: |
135 |
- s=clients[fileno] |
136 |
- record=s.recv(8192) |
137 |
- |
138 |
- if not record: # if connection was closed |
139 |
- epoll.unregister(fileno) |
140 |
- clients[fileno].close() |
141 |
- del clients[fileno] |
142 |
- connects-=1 |
143 |
- #print "closed %d"%fileno |
144 |
- continue |
145 |
- |
146 |
- message=record.split("\0") |
147 |
- #print message |
148 |
- |
149 |
- try: |
150 |
- if message[4]=="ASKING": |
151 |
- if filterproc(message[1],message[2],message[3]): |
152 |
- #print "Allowing an access to %s" % message[2] |
153 |
- s.sendall("ALLOW\0"); # TODO: think about flush here |
154 |
- |
155 |
- else: |
156 |
- print "Blocking an access to %s" % message[2] |
157 |
- s.sendall("DENY\0"); # TODO: think about flush here |
158 |
- |
159 |
+ |
160 |
+ while True: |
161 |
+ try: |
162 |
+ sock_events = epoll.poll(3) |
163 |
+ |
164 |
+ for fileno, sock_event in sock_events: |
165 |
+ if fileno == sock_listen.fileno(): |
166 |
+ #print "\n\nEVENT\n\n" |
167 |
+ ret = sock_listen.accept() |
168 |
+ #print ret |
169 |
+ if ret is None: |
170 |
+ # print "\n\nPASS\n\n" |
171 |
+ pass |
172 |
else: |
173 |
- eventname,filename,stage,result=message[1:5] |
174 |
+ (client,addr)=ret |
175 |
+ # print client |
176 |
+ connects+=1; # client accepted |
177 |
+ was_first_connect=True |
178 |
+ epoll.register(client.fileno(), select.EPOLLIN) |
179 |
+ clients[client.fileno()]=client |
180 |
+ #print "opened %d" % client.fileno() |
181 |
+ #elif sock_event & select.EPOLLHUP: |
182 |
+ #epoll.unregister(fileno) |
183 |
+ #clients[fileno].close() |
184 |
+ #del clients[fileno] |
185 |
+ #connects-=1 |
186 |
+ |
187 |
+ elif sock_event & select.EPOLLIN: |
188 |
+ s=clients[fileno] |
189 |
+ record=s.recv(8192) |
190 |
+ |
191 |
+ if not record: # if connection was closed |
192 |
+ epoll.unregister(fileno) |
193 |
+ clients[fileno].close() |
194 |
+ del clients[fileno] |
195 |
+ connects-=1 |
196 |
+ #print "closed %d"%fileno |
197 |
+ continue |
198 |
+ |
199 |
+ message=record.split("\0") |
200 |
+ #print message |
201 |
+ |
202 |
+ try: |
203 |
+ if message[4]=="ASKING": |
204 |
+ if filterproc(message[1],message[2],message[3]): |
205 |
+ #print "Allowing an access to %s" % message[2] |
206 |
+ s.sendall("ALLOW\0"); # TODO: think about flush here |
207 |
+ |
208 |
+ else: |
209 |
+ print "Blocking an access to %s" % message[2] |
210 |
+ s.sendall("DENY\0"); # TODO: think about flush here |
211 |
+ |
212 |
+ else: |
213 |
+ eventname,filename,stage,result=message[1:5] |
214 |
|
215 |
- if not stage in events: |
216 |
- events[stage]=[{},{}] |
217 |
- |
218 |
- hashofsucesses=events[stage][0] |
219 |
- hashoffailures=events[stage][1] |
220 |
- |
221 |
- if result=="OK": |
222 |
- if not filename in hashofsucesses: |
223 |
- hashofsucesses[filename]=[False,False] |
224 |
+ if not stage in events: |
225 |
+ events[stage]=[{},{}] |
226 |
|
227 |
- readed_or_writed=hashofsucesses[filename] |
228 |
+ hashofsucesses=events[stage][0] |
229 |
+ hashoffailures=events[stage][1] |
230 |
|
231 |
- if eventname=="read": |
232 |
- readed_or_writed[0]=True |
233 |
- elif eventname=="write": |
234 |
- readed_or_writed[1]=True |
235 |
+ if result=="OK": |
236 |
+ if not filename in hashofsucesses: |
237 |
+ hashofsucesses[filename]=[False,False] |
238 |
|
239 |
- elif result[0:3]=="ERR" or result=="DENIED": |
240 |
- if not filename in hashoffailures: |
241 |
- hashoffailures[filename]=[False,False] |
242 |
- notfound_or_blocked=hashoffailures[filename] |
243 |
- |
244 |
- if result=="ERR/2": |
245 |
- notfound_or_blocked[0]=True |
246 |
- elif result=="DENIED": |
247 |
- notfound_or_blocked[1]=True |
248 |
+ readed_or_writed=hashofsucesses[filename] |
249 |
+ |
250 |
+ if eventname=="read": |
251 |
+ readed_or_writed[0]=True |
252 |
+ elif eventname=="write": |
253 |
+ readed_or_writed[1]=True |
254 |
+ |
255 |
+ elif result[0:3]=="ERR" or result=="DENIED": |
256 |
+ if not filename in hashoffailures: |
257 |
+ hashoffailures[filename]=[False,False] |
258 |
+ notfound_or_blocked=hashoffailures[filename] |
259 |
+ |
260 |
+ if result=="ERR/2": |
261 |
+ notfound_or_blocked[0]=True |
262 |
+ elif result=="DENIED": |
263 |
+ notfound_or_blocked[1]=True |
264 |
|
265 |
- else: |
266 |
- print "Error in logger module<->analyser protocol" |
267 |
- |
268 |
- except IndexError: |
269 |
- print "IndexError while parsing %s"%record |
270 |
+ else: |
271 |
+ print "Error in logger module<->analyser protocol" |
272 |
+ |
273 |
+ except IndexError: |
274 |
+ print "IndexError while parsing %s"%record |
275 |
+ except IOError, e: |
276 |
+ if e.errno!=4: # handling "Interrupted system call" errors |
277 |
+ raise |
278 |
|
279 |
if was_first_connect and connects==0: |
280 |
break |
281 |
@@ -264,15 +261,17 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter) |
282 |
"Check that you are not launching a suid program under non-root user." |
283 |
return [] |
284 |
if len(clients)==0 and iszombie(pid): |
285 |
- break |
286 |
- |
287 |
- #print "\n\nRETURNING!!!!\n\n" |
288 |
- |
289 |
+ break |
290 |
|
291 |
- os.wait() |
292 |
+ #print "\n\nRETURNING!!!!\n\n" |
293 |
|
294 |
epoll.unregister(sock_listen.fileno()) |
295 |
epoll.close() |
296 |
sock_listen.close() |
297 |
+ |
298 |
+ _, exit_status=os.waitpid(pid,0) |
299 |
+ signal,exit_status=exit_status%256,exit_status/256 |
300 |
+ print "Signal: %s Exit status: %s" % (signal,exit_status) |
301 |
+ |
302 |
return events |
303 |
|
304 |
|
305 |
diff --git a/logger/src/autodep/logfs/logger_fusefs.py b/logger/src/autodep/logfs/logger_fusefs.py |
306 |
index 9990ef9..6c135e8 100644 |
307 |
--- a/logger/src/autodep/logfs/logger_fusefs.py |
308 |
+++ b/logger/src/autodep/logfs/logger_fusefs.py |
309 |
@@ -4,6 +4,8 @@ import subprocess |
310 |
import time |
311 |
import os |
312 |
import sys |
313 |
+import signal |
314 |
+ |
315 |
|
316 |
|
317 |
class logger: |
318 |
@@ -47,6 +49,7 @@ class logger: |
319 |
os.environ["LOG_SOCKET"]=self.socketname |
320 |
os.environ["PARENT_PID"]=str(self.currpid) |
321 |
|
322 |
+ # TODO: change |
323 |
ret=subprocess.call(['/home/bay/gsoc/logger/src/hook_fusefs/hookfs',self.rootmountpath, |
324 |
'-o','allow_other,suid']) |
325 |
if ret!=0: |
326 |
@@ -102,7 +105,12 @@ class logger: |
327 |
sys.exit(1) |
328 |
|
329 |
else: |
330 |
- exitcode=os.wait()[1]; |
331 |
+ exitcode=2; # if ctrl-c pressed then returning this value |
332 |
+ needtokillself=False |
333 |
+ try: |
334 |
+ exitcode=os.wait()[1]/256; |
335 |
+ except KeyboardInterrupt: |
336 |
+ needtokillself=True |
337 |
try: |
338 |
print "Unmounting partitions" |
339 |
self.mountlist.reverse() |
340 |
@@ -118,4 +126,7 @@ class logger: |
341 |
print "Error while unmounting fuse filesystem: %s" % e |
342 |
sys.exit(1) |
343 |
|
344 |
- sys.exit(int(exitcode/256)) |
345 |
+ if needtokillself: # we kill self for report the status correct |
346 |
+ signal.signal(signal.SIGINT,signal.SIG_DFL) |
347 |
+ os.kill(os.getpid(),signal.SIGINT) |
348 |
+ os._exit(exitcode) |
349 |
|
350 |
diff --git a/logger/src/autodep/logfs/logger_hooklib.py b/logger/src/autodep/logfs/logger_hooklib.py |
351 |
index cda22b6..008fc56 100644 |
352 |
--- a/logger/src/autodep/logfs/logger_hooklib.py |
353 |
+++ b/logger/src/autodep/logfs/logger_hooklib.py |
354 |
@@ -20,3 +20,4 @@ class logger: |
355 |
except OSError, e: |
356 |
print "Failed to launch the programm: %s" % e |
357 |
sys.exit(1) |
358 |
+ |
359 |
|
360 |
diff --git a/logger/src/autodep/showfsevents.py b/logger/src/autodep/showfsevents.py |
361 |
index 3af07d0..aa03d9f 100755 |
362 |
--- a/logger/src/autodep/showfsevents.py |
363 |
+++ b/logger/src/autodep/showfsevents.py |
364 |
@@ -12,9 +12,9 @@ if len(sys.argv)<2: |
365 |
print "Usage: showfsevents.py <command>" |
366 |
exit(1) |
367 |
|
368 |
-events=logfs.fstracer.getfsevents(sys.argv[1], sys.argv[1:],approach="hooklib") |
369 |
+events=logfs.fstracer.getfsevents(sys.argv[1], sys.argv[1:],approach="fusefs") |
370 |
print "Program finished, analyzing dependencies" |
371 |
-#exit(0); |
372 |
+exit(0); |
373 |
# get unique filenames |
374 |
filenames={} |
375 |
for stage in events: |
376 |
@@ -27,8 +27,8 @@ for stage in events: |
377 |
filenames=filenames.keys(); |
378 |
|
379 |
# temporary disabled |
380 |
-file_to_package=logfs.portage_utils.getpackagesbyfiles(filenames) |
381 |
-#file_to_package={} |
382 |
+#file_to_package=logfs.portage_utils.getpackagesbyfiles(filenames) |
383 |
+file_to_package={} |
384 |
#print events |
385 |
|
386 |
stagesorder={"clean":1,"setup":2,"unpack":3,"prepare":4,"configure":5,"compile":6,"test":7, |