Make the estat a command of its own.
[doldaconnect.git] / lib / guile / autodl
CommitLineData
d3372da9 1#!/usr/bin/guile -s
2!#
3
4(use-modules (dolcon ui))
5(use-modules (ice-9 pretty-print))
6
7(define sr '())
8(define lastsearch 0)
9(define info-searcheta 0)
10(define info-numavail 0)
11(define info-numreal 0)
12(define info-numtotal 0)
13(define lastparse 0)
14(define srchid -1)
15(define session '())
16(define trans '())
17(define dpeers '())
18(define lastdl 0)
e6485bff 19(define logport (current-output-port))
20(define infoport #f)
d3372da9 21
c6cc011b 22(define (logf fmt . msg)
e6485bff 23 (if logport
24 (begin
25 (apply format (cons* logport (string-append fmt "\n") msg))
26 (catch 'system-error (lambda ()
27 (fsync logport))
28 (lambda (key . err) #f))))
29 )
30
30806d5e 31(define (infomsg fmt . msg)
e6485bff 32 (if infoport
33 (begin
34 (apply format (cons* infoport (string-append fmt "\n") msg))
35 (catch 'system-error (lambda ()
36 (fsync infoport))
37 (lambda (key . err) #f))))
d3372da9 38 )
39
40(define (make-getopt opts optdesc)
41 (let ((arg opts) (curpos 0) (rest '()))
42 (lambda ()
43 (if (eq? arg '()) rest
44 (let ((ret #f))
45 (while (not ret)
46 (if (= curpos 0)
47 (if (eq? (string-ref (car arg) 0) #\-)
48 (set! curpos 1)
49 (begin
50 (set! rest (append rest (list (car arg))))
51 (set! arg (cdr arg))
52 (if (eq? arg '())
53 (set! ret #t)))))
54 (if (> curpos 0)
55 (if (< curpos (string-length (car arg)))
56 (begin (set! ret (string-ref (car arg) curpos)) (set! curpos (+ curpos 1)))
57 (begin (set! curpos 0) (set! arg (cdr arg)) (if (eq? arg '()) (set! ret #t))))))
58 (if (eq? ret #t) rest
59 (let ((opt (string-index optdesc ret)))
60 (if (eq? opt #f) (throw 'illegal-option ret)
61 (if (and (< opt (- (string-length optdesc) 1)) (eq? (string-ref optdesc (+ opt 1)) #\:))
62 (let ((ret
63 (cons ret (let ((optarg
64 (if (< curpos (string-length (car arg)))
65 (substring (car arg) curpos)
66 (begin (set! arg (cdr arg)) (if (eq? arg '()) (throw 'requires-argument ret)) (car arg)))))
67 (set! arg (cdr arg)) optarg))))
68 (set! curpos 0)
69 ret)
70 (list ret))))))))))
71
72(define (ftime)
73 (let ((ctime (gettimeofday)))
74 (+ (car ctime) (/ (cdr ctime) 1000000))))
75
76(define (wanttosearch)
77 (> (- (current-time) lastsearch)
d30cc4bc 78 (if (eq? (cdr (assoc 'search-mode session)) 'wait)
79 7200
80 (if (> (length trans) 0) 300 60)))
d3372da9 81 )
82
83(define defspeed '())
84(let ((matchlist (list
85 (cons (make-regexp "^[][{}() ]*BBB" regexp/icase) 100000))))
86 (set! defspeed
87 (lambda (sr)
88 (catch 'ret
89 (lambda ()
90 (for-each (lambda (o)
91 (if (regexp-exec (car o) (cadr (cdr (assoc 'peer sr))))
92 (throw 'ret (cdr o))))
93 matchlist)
94 15000)
95 (lambda (sig ret)
96 ret))
97 )))
98
99(define (sr-less? sr1 sr2)
100 (let ((s1 (if (cdr (assoc 'speed sr1)) (cdr (assoc 'speed sr1)) (defspeed sr1)))
101 (s2 (if (cdr (assoc 'speed sr2)) (cdr (assoc 'speed sr2)) (defspeed sr2))))
102 (if (= s1 s2)
103 (< (cdr (assoc 'resptime sr1)) (cdr (assoc 'resptime sr2)))
104 (> s1 s2)))
105 )
106
107(define (srg-less? g1 g2)
108 (or (> (length (cdr g1)) (length (cdr g2)))
109 (and (= (length (cdr g1)) (length (cdr g2)))
110 (> (car g1) (car g2))))
111 )
112
113(define (gettrbysize size)
114 (catch 'ret
115 (lambda ()
116 (for-each (lambda (o)
117 (if (= (cdr (assoc 'size (cdr o))) size)
118 (throw 'ret (cdr o))))
119 trans)
120 #f)
121 (lambda (sig ret)
122 ret))
123 )
124
125(define (download sr)
126 (let ((resp #f))
127 (let ((args (list "download"
128 (car (cdr (assoc 'peer sr)))
129 (cadr (cdr (assoc 'peer sr)))
130 (cdr (assoc 'filename sr))
131 (cdr (assoc 'size sr)))))
3b0de0fd 132 (let ((hash (assoc 'hash sr)))
133 (if (and hash (not (equal? (cdr hash) ""))) (set! args (append args (list "hash" (cdr hash))))))
d3372da9 134 (let ((tag (assoc 'tag session)))
135 (if tag (set! args (append args (list "tag" (cdr tag))))))
136 (let ((uarg (assoc 'uarg session)))
137 (if uarg (set! args (append args (list "user" (cdr uarg))))))
e838f46b 138 (let ((xargs (assoc 'xargs session)))
139 (if xargs (for-each (lambda (o)
140 (set! args (append args (list (car o) (cdr o)))))
141 (cdr xargs))))
d3372da9 142 (set! resp (apply dc-ecmd-assert 200 args)))
143 (let ((id (car (dc-intresp resp))))
144 (set! trans
145 (cons (cons id (list (assoc 'size sr)
146 (assoc 'peer sr)
147 (assoc 'filename sr)
148 (assoc 'resptime sr)
149 '(curpos . 0)
150 '(state . wait)
151 '(curspeed . #f)
152 '(lastpos . 0)
153 (cons 'id id)
154 (cons 'lasttime (current-time))
155 (cons 'lastprog (current-time))))
156 trans))
c6cc011b 157 (logf "downloading ~a from ~a, ~a bytes (id ~a, ~a slots), timing out in ~a seconds"
158 (cdr (assoc 'filename sr))
159 (cadr (cdr (assoc 'peer sr)))
e6485bff 160 (cdr (assoc 'size sr))
161 id
162 (cdr (assoc 'slots sr))
163 (max 10 (* (cdr (assoc 'resptime sr)) 2)))
164 (infomsg "dl ~a ~a" (cdr (assoc 'size sr)) id)))
d3372da9 165 (set! lastdl (current-time))
166 )
167
168(define (disablepeer peer)
169 (let ((newglist '()) (numrem 0))
170 (for-each (lambda (g)
171 (let ((newlist '()))
172 (for-each (lambda (o)
173 (if (not (equal? (cdr (assoc 'peer o)) peer))
174 (set! newlist (cons o newlist))
175 (set! numrem (+ numrem 1))))
176 (cdr g))
177 (if (not (eq? newlist '()))
178 (set! newglist (cons (cons (car g) (sort newlist sr-less?)) newglist)))))
179 sr)
180 (set! sr (sort newglist srg-less?))
c6cc011b 181 (logf "disabled ~a and removed ~a search results" (cadr peer) numrem))
d3372da9 182 (let* ((dpa (assoc peer dpeers)) (dp (and (pair? dpa) (cdr dpa))))
183 (if dp
184 (set-cdr! (assoc 'time dp) (current-time))
185 (set! dpeers (cons (cons peer (list (cons 'time (current-time))
186 (cons 'peer peer)))
187 dpeers))))
188 )
189
190(define (checktrans)
191 (let ((time (current-time)))
192 (for-each (lambda (o)
193 (if (and (memq (cdr (assoc 'state (cdr o))) '(wait hs))
194 (> (- time (cdr (assoc 'lastprog (cdr o)))) (max 10 (* (cdr (assoc 'resptime (cdr o))) 2))))
c6cc011b 195 (begin (logf "transfer ~a timing out" (car o))
e6485bff 196 (infomsg "dlstop ~a timeout" (car o))
d3372da9 197 (dc-ecmd-assert 200 "cancel" (car o))
198 (disablepeer (cdr (assoc 'peer (cdr o))))
ecd6e23d 199 (set! trans (assq-remove! trans (car o)))
200 (write-info-file)))
d3372da9 201 (if (and (eq? (cdr (assoc 'state (cdr o))) 'main)
202 (> (- time (cdr (assoc 'lastprog (cdr o)))) 60))
c6cc011b 203 (begin (logf "transfer ~a seems to have stalled" (car o))
e6485bff 204 (infomsg "dlstop ~a stall" (car o))
d3372da9 205 (dc-ecmd-assert 200 "cancel" (car o))
ecd6e23d 206 (set! trans (assq-remove! trans (car o)))
207 (write-info-file)))
d3372da9 208 (if (and (eq? (cdr (assoc 'state (cdr o))) 'main)
209 (> (- (cdr (assoc 'lastprog (cdr o))) (cdr (assoc 'lasttime (cdr o)))) 20))
210 (begin (set-cdr! (assoc 'curspeed (cdr o))
211 (/ (- (cdr (assoc 'curpos (cdr o))) (cdr (assoc 'lastpos (cdr o))))
212 (- (cdr (assoc 'lastprog (cdr o))) (cdr (assoc 'lasttime (cdr o))))))
213 (set-cdr! (assoc 'lastpos (cdr o)) (cdr (assoc 'curpos (cdr o))))
ecd6e23d 214 (set-cdr! (assoc 'lasttime (cdr o)) (cdr (assoc 'lastprog (cdr o))))
215 (write-info-file))))
d3372da9 216 trans))
217 )
218
219(define (write-info-file)
220 (if (assoc 'info-file session)
221 (let ((op (open-output-file (cdr (assoc 'info-file session)))))
d576878b 222 (pretty-print (list (cons 'numdl (length trans))
223 (cons 'lastdl lastdl)
224 (cons 'availsr info-numavail)
225 (cons 'realsr info-numreal)
226 (cons 'totalsr info-numtotal)
227 (cons 'lastsrch lastsearch)
228 (cons 'srcheta info-searcheta)
229 (cons 'srchmode (cdr (assoc 'search-mode session))))
230 op)
d3372da9 231 (close-port op))))
232
233(define (parseresults)
c6cc011b 234 (logf "entering parseresults with ~a results in ~a sizes"
235 (apply + (map (lambda (o) (length (cdr o))) sr))
236 (number->string (length sr)))
e6485bff 237 (infomsg "srs ~a"
238 (apply + (map (lambda (o) (length (cdr o))) sr)))
d3372da9 239 (let ((retval #t) (numreal 0) (numtotal 0) (numavail 0))
240 (catch 'ret
241 (lambda ()
242 (and (eq? sr '()) (throw 'ret #f))
243 (let ((numrem 0) (countrem 0) (newglist '()))
244 (for-each (lambda (g)
245 (let ((newlist '()))
246 (for-each (lambda (o)
247 (if (< (- (current-time) (cdr (assoc 'recvtime o))) 300)
248 (set! newlist (cons o newlist))
249 (set! countrem (+ countrem 1))))
250 (cdr g))
251 (if (> (length newlist) 0)
252 (set! newglist (cons (cons (car g) (sort newlist sr-less?)) newglist))
253 (set! numrem (+ numrem 1)))))
254 sr)
255 (set! sr (sort newglist srg-less?))
256 (if (> countrem 0)
c6cc011b 257 (logf "removed ~a time-outed results and ~a entire sizes" countrem numrem)))
d3372da9 258 (let ((numrem 0) (newlist '()))
259 (for-each (lambda (o)
260 (if (> (- (current-time) (cdr (assoc 'time o))) 1800)
261 (set! numrem (+ numrem 1))
262 (set! newlist (cons o newlist))))
263 dpeers)
264 (set! dpeers newlist)
c6cc011b 265 (logf "re-enabled ~a disabled users" numrem))
d3372da9 266 (let ((numrem 0) (countrem 0) (newglist '()))
267 (for-each (lambda (g)
268 (let ((newlist '()))
269 (for-each (lambda (o)
270 (if (not (assoc (cdr (assoc 'peer o)) dpeers))
271 (set! newlist (cons o newlist))
272 (set! countrem (+ countrem 1))))
273 (cdr g))
274 (if (> (length newlist) 0)
275 (set! newglist (cons (cons (car g) (sort newlist sr-less?)) newglist))
276 (set! numrem (+ numrem 1)))))
277 sr)
278 (set! sr (sort newglist srg-less?))
279 (if (> countrem 0)
c6cc011b 280 (logf "removed ~a results with disabled peers and ~a entire sizes" countrem numrem)))
d3372da9 281 (and (eq? sr '()) (throw 'ret #f))
282 (set! numtotal (apply + (map (lambda (o) (length (cdr o))) sr)))
283 (let* ((maxsize (apply max (map (lambda (o) (length (cdr o))) sr)))
284 (minsize (/ maxsize 3)))
285 (let ((numrem 0) (countrem 0))
286 (for-each (lambda (o) (if (< (length (cdr o)) minsize)
287 (begin (set! countrem (+ countrem (length (cdr o))))
288 (set! numrem (+ numrem 1)))))
289 sr)
290 (if (> countrem 0)
c6cc011b 291 (logf "will disregard ~a results from ~a sizes due to popularity lack" countrem numrem))
d3372da9 292 (set! numreal (- numtotal countrem)))
293 (let ((numrem 0) (numrrem 0))
294 (for-each (lambda (g)
295 (for-each (lambda (o)
296 (if (< (cdr (assoc 'slots o)) 1)
297 (begin (set! numrem (+ numrem 1))
298 (if (>= (length (cdr g)) minsize)
299 (set! numrrem (+ numrrem 1))))))
300 (cdr g)))
301 sr)
302 (if (> numrem 0)
c6cc011b 303 (logf "~a results had no slots" numrem))
d3372da9 304 (set! numavail (- numreal numrrem)))
305 (for-each (lambda (g)
306 (if (>= (length (cdr g)) minsize)
307 (catch 'found
308 (lambda ()
309 (for-each (lambda (o)
310 (and (> (cdr (assoc 'slots o)) 0)
311 (throw 'found o)))
312 (cdr g)))
313 (lambda (sig sr)
314 (let ((tr (gettrbysize (cdr (assoc 'size sr)))))
315 (if (not tr)
316 (if (< (length trans) (cdr (assoc 'maxtrans session)))
317 (download sr))
318 (if (and (cdr (assoc 'curspeed tr))
319 (not (equal? (cdr (assoc 'peer sr)) (cdr (assoc 'peer tr))))
320 (> (- (or (cdr (assoc 'speed sr)) (defspeed sr)) (cdr (assoc 'curspeed tr))) 10000))
c6cc011b 321 (begin (logf "abandoning transfer ~a for possible faster sender"
322 (cdr (assoc 'id tr)))
e6485bff 323 (infomsg "dlstop ~a tryother" (cdr (assoc 'id tr)))
d3372da9 324 (dc-ecmd-assert 200 "cancel" (cdr (assoc 'id tr)))
325 (set! trans (assq-remove! trans (cdr (assoc 'id tr))))
326 (download sr)))))))))
327 sr)
328 )
329 )
330 (lambda (sig ret)
331 (set! retval ret)
332 ))
333 (set! info-numavail numavail)
334 (set! info-numreal numreal)
335 (set! info-numtotal numtotal)
ecd6e23d 336 (write-info-file)
d3372da9 337 retval)
338 )
339
3b0de0fd 340(define (handlesr filename fnet peer size slots resptime hash)
2bb57f49 341 (if (eq? (cdr (assoc 'search-mode session)) 'wait)
342 (begin (set-cdr! (assoc 'search-mode session) 'normal)
e6485bff 343 (logf "reverting to normal mode")
344 (infomsg "searchmode normal")))
d3372da9 345 (let ((cl (or (assoc size sr)
346 (let ((newp (cons size '()))) (set! sr (append sr (list newp))) newp)))
347 (newsr (list
348 (cons 'filename filename)
349 (cons 'peer (list fnet peer))
350 (cons 'size size)
351 (cons 'slots slots)
352 (cons 'resptime resptime)
353 (cons 'speed (getspeed peer))
3b0de0fd 354 (cons 'hash hash)
d3372da9 355 (cons 'recvtime (current-time))
356 (cons 'dis #f)))
357 (newlist '()))
358 (for-each (lambda (o) (if (not (and (equal? (cdr (assoc 'filename o)) filename)
359 (equal? (cdr (assoc 'peer o)) (list fnet peer))))
360 (set! newlist (cons o newlist))))
361 (cdr cl))
362 (set-cdr! cl (sort (cons newsr newlist) sr-less?))
363 )
364 )
365
366; XXX: Redefine to go through the server, once that is implemented
367(define (getspeed username)
368 (catch 'system-error
369 (lambda ()
370 (let* ((port (open-input-file (string-append (getenv "HOME") "/dc/users/" username))) (avg 0) (numdls (string->number (read-line port))) (max (string->number (read-line port))) (numents (string->number (read-line port))))
371 (do ((i 0 (+ i 1))) ((= i numents) (close-port port) (/ avg numents)) (set! avg (+ avg (string->number (read-line port)))))
372 ))
373 (lambda args
374 #f
375 )
376 )
377 )
378
379(define (validate-session session)
380 (catch 'wrong-type-arg
381 (lambda ()
382 (and
383 (assoc 'sexpr session)
384 (assoc 'prio session)
385 (assoc 'maxtrans session)
386 #t
387 )
388 )
389 (lambda (key . args)
390 (display "Session data is not an a-list\n" (current-error-port))
391 #f)
392 )
393 )
394
395(define (autodl-main args)
aa82fda0 396 (let ((dc-server #f) (done #f) (retval 0) (filterexit ""))
e6485bff 397 (let ((getopt (make-getopt (cdr args) "whis:S:e:p:t:a:I:E:x:")) (arg #f))
d3372da9 398 (do ((arg (getopt) (getopt))) ((not (and (pair? arg) (char? (car arg)))) (set! args arg))
399 (cond ((eq? (car arg) #\h)
400 (begin (display "usage: autodl [-s server] -S sessfile\n" (current-error-port))
d30cc4bc 401 (display " autodl [-w] [-s server] -e search-expression [-p prio] [-t tag] [-a userarg]\n" (current-error-port))
d3372da9 402 (display " autodl [-s server]\n" (current-error-port))
403 (display " autodl -h\n" (current-error-port))
404 (exit 0)))
405 ((eq? (car arg) #\s)
406 (set! dc-server (cdr arg)))
407 ((eq? (car arg) #\S)
408 (let ((port (open-file (cdr arg)))) (set! session (read port)) (close-port port)))
409 ((eq? (car arg) #\p)
410 (let ((c (assoc 'prio session)))
411 (if c (set-cdr! c (cdr arg))
412 (set! session (cons (cons 'prio (cdr arg)) session)))))
413 ((eq? (car arg) #\t)
414 (let ((c (assoc 'tag session)))
415 (if c (set-cdr! c (cdr arg))
416 (set! session (cons (cons 'tag (cdr arg)) session)))))
417 ((eq? (car arg) #\a)
418 (let ((c (assoc 'uarg session)))
419 (if c (set-cdr! c (cdr arg))
420 (set! session (cons (cons 'uarg (cdr arg)) session)))))
421 ((eq? (car arg) #\I)
422 (let ((c (assoc 'info-file session)))
423 (if c (set-cdr! c (cdr arg))
424 (set! session (cons (cons 'info-file (cdr arg)) session)))))
e6485bff 425 ((eq? (car arg) #\i)
426 (set! infoport logport)
427 (set! logport #f))
aa82fda0 428 ((eq? (car arg) #\E)
429 (let ((c (assoc 'estat-file session)))
430 (if c (set-cdr! c (cdr arg))
431 (set! session (cons (cons 'estat-file (cdr arg)) session)))))
d3372da9 432 ((eq? (car arg) #\e)
433 (set! session (cons (cons 'sexpr (dc-lexsexpr (cdr arg))) session)))
d30cc4bc 434 ((eq? (car arg) #\w)
435 (set! session (cons '(search-mode . wait) session)))
e838f46b 436 ((eq? (car arg) #\x)
437 (let* ((c (assoc 'xargs session)) (p (string-index (cdr arg) #\=))
438 (recons (cons (substring (cdr arg) 0 p) (substring (cdr arg) (1+ p)))))
439 (if c (set-cdr! c (cons recons (cdr c)))
440 (set! session (cons (cons 'xargs (list recons)) session)))))
d3372da9 441 )
442 )
443 )
444 (if (eq? session '()) (begin (if (isatty? (current-input-port)) (display "Enter session data (s-expr):\n" (current-error-port))) (set! session (read))))
445 (if (not (assoc 'prio session))
446 (set! session (cons '(prio . 10) session)))
447 (if (not (assoc 'maxtrans session))
448 (set! session (cons '(maxtrans . 1) session)))
d30cc4bc 449 (if (not (assoc 'search-mode session))
53acfa81 450 (set! session (cons '(search-mode . normal) session)))
d3372da9 451 (if (not (validate-session session)) (begin (display "Invalid session!\n" (current-error-port)) (exit 1)))
452 (if (not dc-server) (set! dc-server (getenv "DCSERVER")))
453 (if (not dc-server) (set! dc-server "localhost"))
454 (catch 'system-error
455 (lambda ()
6d8a9842 456 (dc-c&l #f dc-server #t))
d3372da9 457 (lambda (key . args)
c6cc011b 458 (logf "could not connect to server: ~a" (apply format #f (cadr args) (caddr args)))
d3372da9 459 (exit 2)))
c6a77cc5 460 (dc-ecmd-assert 200 "notify" "trans:act" "on" "trans:prog" "on" "srch:act" "on")
d3372da9 461 (for-each (lambda (sig) (sigaction sig (lambda (sig) (throw 'sig sig)))) (list SIGINT SIGTERM SIGHUP))
462 (catch 'sig
463 (lambda ()
464 (while #t
465 (if (and (not (= lastsearch -1)) (wanttosearch))
466 (begin
467 (if (not (= srchid -1))
468 (dc-ecmd "cansrch" srchid))
469 (let* ((resp (apply dc-ecmd-assert (append (list '(200 501 509) "search" "prio" (number->string (cdr (assoc 'prio session))) "all") (cdr (assoc 'sexpr session)))))
470 (ires (dc-intresp resp))
471 (eres (dc-extract resp)))
472 (case (cdr (assoc 'code eres))
473 ((200)
474 (begin (set! srchid (car ires))
c6cc011b 475 (logf "search scheduled in ~a seconds (id ~a)"
e6485bff 476 (cadr ires)
477 srchid)
478 (infomsg "search pending ~a" (cadr ires))
d3372da9 479 (set! info-searcheta (+ (current-time) (cadr ires)))
ecd6e23d 480 (set! lastsearch -1)
481 (write-info-file)))
d3372da9 482 ((501)
483 (begin (set! srchid -1)
c6cc011b 484 (logf "no fnetnodes available to search on")
e6485bff 485 (infomsg "nofns")
d3372da9 486 (set! lastsearch (current-time))))
487 ((509)
488 (begin (logf "illegal search expression")
489 (set! done #t)
490 (set! retval 3)
491 (throw 'sig 0)))))))
492 (checktrans)
493 (if (> (- (current-time) lastparse) 20)
494 (begin (parseresults)
495 (set! lastparse (current-time))))
d3372da9 496 (dc-select 10000)
497 (while (let ((resp (dc-getresp)))
498 (if resp
499 (begin
500 (let* ((er (dc-extract resp)) (code (cdr (assoc 'code er))) (cmd (cdr (assoc 'cmd er))))
501 (cond
502 ((equal? cmd ".notify")
503 (case code
504 ((611) ; Transfer state change
505 (let ((ires (dc-intresp resp)) (tr #f))
506 (if (and ires (assoc (car ires) trans))
507 (begin (set! tr (cdr (assoc (car ires) trans)))
508 (set-cdr! (assoc 'state tr)
509 (cdr (assoc (cadr ires) '((0 . wait) (1 . hs) (2 . main) (3 . done)))))
510 (set-cdr! (assoc 'lastprog tr) (current-time))))))
511 ((614) ; Transfer error
512 (let ((ires (dc-intresp resp)))
513 (if (and ires (assoc (car ires) trans))
c6cc011b 514 (begin (logf "transfer ~a encountered error ~a" (car ires) (cadr ires))
e6485bff 515 (infomsg "dlstop ~a error ~a" (car ires) (cadr ires))
d3372da9 516 (dc-ecmd-assert 200 "cancel" (car ires))
517 (let ((tr (cdr (assoc (car ires) trans))))
518 (disablepeer (cdr (assoc 'peer tr))))
519 (set! trans (assq-remove! trans (car ires)))))))
520 ((615) ; Transfer progress
521 (let ((ires (dc-intresp resp)) (tr #f))
522 (if (and ires (assoc (car ires) trans))
523 (begin (set! tr (cdr (assoc (car ires) trans)))
524 (set-cdr! (assoc 'curpos tr) (cadr ires))
525 (set-cdr! (assoc 'lastprog tr) (current-time))))))
526 ((617) ; Transfer destroyed
527 (let* ((ires (dc-intresp resp)) (tr (and ires (assoc (car ires) trans))))
528 (if tr
529 (begin (if (eq? (cdr (assoc 'state (cdr tr))) 'done)
c6cc011b 530 (begin (logf "transfer ~a done (~a)" (car ires) (cadr ires))
42a9c63a 531 (infomsg "dldone ~a" (car ires))
532 (infomsg "estat ~a" (cadr ires))
d3372da9 533 (set! trans (assq-remove! trans (car ires)))
534 (set! done #t)
2fc2772d 535 (set! filterexit (cadr ires))
d3372da9 536 (throw 'sig 0))
c6cc011b 537 (begin (logf "transfer ~a disappeared" (car ires))
e6485bff 538 (infomsg "dlstop ~a gone" (car ires))
d3372da9 539 (set! trans (assq-remove! trans (car ires)))))))))
540 ((620) ; Search rescheduled
541 (let ((ires (dc-intresp resp)))
542 (if (and ires (= (car ires) srchid))
543 (begin (set! info-searcheta (+ (current-time) (cadr ires)))
c6cc011b 544 (logf "search rescheduled to T+~a" (cadr ires))
e6485bff 545 (infomsg "search pending ~a" (cadr ires))
d30cc4bc 546 (write-info-file)))))
d3372da9 547 ((621) ; Search committed
548 (let ((ires (dc-intresp resp)))
549 (if (and ires (= (car ires) srchid))
550 (begin (logf "search committed")
e6485bff 551 (infomsg "search commit")
d3372da9 552 (set! info-searcheta 0)
d30cc4bc 553 (set! lastsearch (current-time))
554 (write-info-file)))))
d3372da9 555 ((622) ; Search result
556 (let ((ires (list->vector (dc-intresp resp))))
3b0de0fd 557 (if (and ires (= (vector-ref ires 0) srchid)) (apply handlesr (map (lambda (n) (vector-ref ires n)) '(1 2 3 4 5 7 8))))))
d3372da9 558
559 )
560 )
561
562 )
563 )
564 #t)
565 #f)
566 )
567 #t
568 )
569 )
570 )
571 (lambda (key sig)
c6cc011b 572 (logf "interrupted by signal ~a" sig)
d3372da9 573 (if (not done)
574 (set! retval 1)))
575 )
576 (logf "quitting...")
577 (catch 'sig
578 (lambda ()
579 (if (dc-connected)
580 (begin (for-each (lambda (o)
581 (dc-qcmd (list "cancel" (car o))))
582 trans)
583 (if (assoc 'info-file session)
584 (catch 'system-error
585 (lambda ()
586 (delete-file (cdr (assoc 'info-file session))))
587 (lambda (key . args) #t)))
588 (if (and done (assoc 'tag session))
589 (dc-qcmd (list "filtercmd" "rmtag" (cdr (assoc 'tag session)))))
590 (if (not (= srchid -1))
591 (dc-qcmd (list "cansrch" srchid)))
592 (dc-qcmd '("quit"))
593 (while (dc-connected) (dc-select))
594 )))
595 (lambda (key sig)
596 (logf "forcing quit")))
aa82fda0 597 (if (assoc 'estat-file session)
598 (let ((op (open-output-file (cdr (assoc 'estat-file session)))))
fc068ee7 599 (display filterexit op)
aa82fda0 600 (newline op)
601 (close-port op)))
d3372da9 602 (exit retval)
603 )
604 )
605
606(setlocale LC_ALL "")
607(autodl-main (command-line))