Line data Source code
1 : /* Client of the server status. Runs on the server machine and connects to the
2 : burp server to get status information. */
3 :
4 : #include "../../burp.h"
5 : #include "../../action.h"
6 : #include "../../alloc.h"
7 : #include "../../asfd.h"
8 : #include "../../async.h"
9 : #include "../../bu.h"
10 : #include "../../cmd.h"
11 : #include "../../cstat.h"
12 : #include "../../forkchild.h"
13 : #include "../../fsops.h"
14 : #include "../../fzp.h"
15 : #include "../../handy.h"
16 : #include "../../iobuf.h"
17 : #include "../../log.h"
18 : #include "json_input.h"
19 : #include "lline.h"
20 : #include "status_client_ncurses.h"
21 :
22 : #ifdef HAVE_NCURSES_H
23 : #include "ncurses.h"
24 : // So that the sighandler can call endwin():
25 : static enum action actg=ACTION_STATUS;
26 : #endif
27 :
28 : #define LEFT_SPACE 3
29 : #define TOP_SPACE 2
30 :
31 : static struct fzp *lfzp=NULL;
32 :
33 : // For switching between seeing 'last backup' and counter summary on the front
34 : // screen.
35 : static uint8_t toggle=0;
36 :
37 0 : static void print_line(const char *string, int row, int col)
38 : {
39 0 : int k=0;
40 0 : const char *cp=NULL;
41 : #ifdef HAVE_NCURSES_H
42 0 : if(actg==ACTION_STATUS)
43 : {
44 0 : while(k<LEFT_SPACE) mvprintw(row+TOP_SPACE, k++, " ");
45 0 : for(cp=string; (*cp && k<col); cp++)
46 0 : mvprintw(row+TOP_SPACE, k++, "%c", *cp);
47 0 : while(k<col) mvprintw(row+TOP_SPACE, k++, " ");
48 0 : return;
49 : }
50 : #endif
51 0 : while(k<LEFT_SPACE) { printf(" "); k++; }
52 0 : for(cp=string; *cp; cp++)
53 : {
54 0 : printf("%c", *cp);
55 0 : k++;
56 : #ifdef HAVE_NCURSES_H
57 0 : if(actg==ACTION_STATUS && k<col) break;
58 : #endif
59 : }
60 0 : printf("\n");
61 : }
62 :
63 0 : static char *get_bu_str(struct bu *bu)
64 : {
65 : static char ret[32];
66 0 : if(!bu) snprintf(ret, sizeof(ret), "never");
67 0 : else if(!bu->bno) snprintf(ret, sizeof(ret), "%s", bu->timestamp);
68 0 : else snprintf(ret, sizeof(ret), "%07lu %s", bu->bno, bu->timestamp);
69 0 : return ret;
70 : }
71 :
72 0 : static void client_summary(struct cstat *cstat,
73 : int row, int col, int clientwidth, struct conf **confs)
74 : {
75 0 : char msg[1024]="";
76 0 : char fmt[64]="";
77 0 : struct bu *cbu=NULL;
78 : snprintf(fmt, sizeof(fmt), "%%-%d.%ds %%9s %%s%%s",
79 0 : clientwidth, clientwidth);
80 :
81 : // Find the current backup.
82 0 : cbu=bu_find_current(cstat->bu);
83 :
84 0 : switch(cstat->run_status)
85 : {
86 : case RUN_STATUS_RUNNING:
87 0 : if(toggle)
88 : {
89 0 : char f[64]="";
90 0 : char b[64]="";
91 0 : uint64_t p=0;
92 0 : uint64_t t=0;
93 0 : struct cntr *cntr=cstat->cntr;
94 : struct cntr_ent *ent_gtotal=
95 0 : cntr->ent[(uint8_t)CMD_GRAND_TOTAL];
96 :
97 : t=ent_gtotal->count
98 0 : +ent_gtotal->same
99 0 : +ent_gtotal->changed;
100 0 : if(ent_gtotal->phase1)
101 0 : p=(t*100)/ent_gtotal->phase1;
102 : snprintf(f, sizeof(f),
103 : " %"PRIu64"/%"PRIu64" %"PRIu64"%%",
104 0 : t, ent_gtotal->phase1, p);
105 0 : if(cntr->byte)
106 : snprintf(b, sizeof(b), "%s",
107 0 : bytes_to_human(cntr->byte));
108 : snprintf(msg, sizeof(msg), fmt,
109 : cstat->name,
110 : run_status_to_str(cstat),
111 0 : f, b);
112 0 : break;
113 : }
114 : // Else fall through.
115 : case RUN_STATUS_IDLE:
116 : case RUN_STATUS_SERVER_CRASHED:
117 : case RUN_STATUS_CLIENT_CRASHED:
118 : default:
119 : snprintf(msg, sizeof(msg), fmt,
120 : cstat->name,
121 : run_status_to_str(cstat),
122 : " last backup: ",
123 0 : get_bu_str(cbu));
124 0 : break;
125 : }
126 :
127 0 : if(*msg) print_line(msg, row, col);
128 0 : }
129 :
130 : /* for the counters */
131 0 : static void to_msg(char msg[], size_t s, const char *fmt, ...)
132 : {
133 : va_list ap;
134 0 : va_start(ap, fmt);
135 0 : vsnprintf(msg, s, fmt, ap);
136 0 : va_end(ap);
137 0 : }
138 :
139 0 : static void print_cntr_ent(const char *field,
140 : uint64_t a,
141 : uint64_t b,
142 : uint64_t c,
143 : uint64_t d,
144 : uint64_t e,
145 : int *x, int col)
146 : {
147 0 : char msg[256]="";
148 0 : uint64_t t=a+b+c;
149 0 : if(!field || (!t && !d && !e)) return;
150 :
151 : /* FIX THIS.
152 : if(phase==STATUS_RESTORING
153 : || phase==STATUS_VERIFYING)
154 : {
155 : to_msg(msg, sizeof(msg),
156 : "% 15s % 9s % 9llu % 9llu",
157 : field, "", t, e);
158 : }
159 : else
160 : {
161 : */
162 : to_msg(msg, sizeof(msg),
163 : "% 15s % 9llu % 9llu % 9llu % 9llu % 9llu % 9llu",
164 0 : field, a, b, c, d, t, e);
165 : // }
166 0 : print_line(msg, (*x)++, col);
167 : /* FIX THIS
168 : if(percent && e)
169 : {
170 : uint64_t p;
171 : p=(t*100)/e;
172 : if(phase==STATUS_RESTORING
173 : || phase==STATUS_VERIFYING)
174 : {
175 : to_msg(msg, sizeof(msg), "% 15s % 9s % 9llu%% % 9s",
176 : "", "", p, "");
177 : }
178 : else
179 : {
180 : to_msg(msg, sizeof(msg), "% 15s % 9s % 9s % 9s % 9s % 9llu%% % 9s",
181 : "", "", "", "", "", p, "");
182 : print_line(msg, (*x)++, col);
183 : }
184 : */
185 : }
186 :
187 0 : static void table_header(int *x, int col)
188 : {
189 0 : char msg[256]="";
190 : /* FIX THIS
191 : if(phase==STATUS_RESTORING
192 : || phase==STATUS_VERIFYING)
193 : {
194 : to_msg(msg, sizeof(msg), "% 15s % 9s % 9s % 9s",
195 : "", "", "Attempted", "Expected");
196 : }
197 : else
198 : {
199 : */
200 : to_msg(msg, sizeof(msg), "% 15s % 9s % 9s % 9s % 9s % 9s % 9s",
201 0 : "", "New", "Changed", "Unchanged", "Deleted", "Total", "Scanned");
202 : // }
203 0 : print_line(msg, (*x)++, col);
204 0 : }
205 :
206 : /*
207 : static void print_detail2(const char *field, uint64_t value1, const char *value2, int *x, int col)
208 : {
209 : char msg[256]="";
210 : if(!field || !value1 || !value2 || !*value2) return;
211 : snprintf(msg, sizeof(msg), "%s: %llu%s", field, value1, value2);
212 : print_line(msg, (*x)++, col);
213 : }
214 :
215 : static void print_detail3(const char *field, const char *value, int *x, int col)
216 : {
217 : char msg[256]="";
218 : if(!field || !value || !*value) return;
219 : snprintf(msg, sizeof(msg), "%s: %s", field, value);
220 : print_line(msg, (*x)++, col);
221 : }
222 : */
223 : /*
224 : static void detail(const char *cntrclient, char status, char phase, const char *path, struct cntr *p1cntr, struct cntr *cntr, struct strlist *backups, int row, int col)
225 : {
226 : int x=0;
227 : char msg[1024]="";
228 : print_line("", x++, col);
229 : table_header(phase, &x, col);
230 :
231 : print_detail(phase, "Files",
232 : cntr->file,
233 : cntr->file_changed,
234 : cntr->file_same,
235 : cntr->file_deleted,
236 : p1cntr->file,
237 : &x, col, 0);
238 : print_detail(phase, "Encrypted files",
239 : cntr->enc,
240 : cntr->enc_changed,
241 : cntr->enc_same,
242 : cntr->enc_deleted,
243 : p1cntr->enc,
244 : &x, col, 0);
245 : print_detail(phase, "Meta data",
246 : cntr->meta,
247 : cntr->meta_changed,
248 : cntr->meta_same,
249 : cntr->meta_deleted,
250 : p1cntr->meta,
251 : &x, col, 0);
252 : print_detail(phase, "Encrypted meta data",
253 : cntr->encmeta,
254 : cntr->encmeta_changed,
255 : cntr->encmeta_same,
256 : cntr->encmeta_deleted,
257 : p1cntr->encmeta,
258 : &x, col, 0);
259 : print_detail(phase, "Directories",
260 : cntr->dir,
261 : cntr->dir_changed,
262 : cntr->dir_same,
263 : cntr->dir_deleted,
264 : p1cntr->dir,
265 : &x, col, 0);
266 : print_detail(phase, "Soft links",
267 : cntr->slink,
268 : cntr->slink_changed,
269 : cntr->slink_same,
270 : cntr->slink_deleted,
271 : p1cntr->slink,
272 : &x, col, 0);
273 : print_detail(phase, "Hard links",
274 : cntr->hlink,
275 : cntr->hlink_changed,
276 : cntr->hlink_same,
277 : cntr->hlink_deleted,
278 : p1cntr->hlink,
279 : &x, col, 0);
280 : print_detail(phase, "Special files",
281 : cntr->special,
282 : cntr->special_changed,
283 : cntr->special_same,
284 : cntr->special_deleted,
285 : p1cntr->special,
286 : &x, col, 0);
287 : print_detail(phase, "Total",
288 : cntr->gtotal,
289 : cntr->gtotal_changed,
290 : cntr->gtotal_same,
291 : cntr->gtotal_deleted,
292 : p1cntr->gtotal,
293 : &x, col, 1);
294 : print_line("", x++, col);
295 : print_detail(phase, "Warnings",
296 : cntr->warning, 0, 0, 0, 0,
297 : &x, col, 1);
298 :
299 : if(p1cntr->byte)
300 : {
301 : tmp=bytes_to_human(p1cntr->byte);
302 : print_detail2("Bytes estimated", p1cntr->byte, tmp, &x, col);
303 : }
304 : if(cntr->byte)
305 : {
306 : const char *text=NULL;
307 : if(phase==STATUS_BACKUP) text="Bytes in backup";
308 : else if(phase==STATUS_RESTORING) text="Bytes attempted";
309 : else if(phase==STATUS_VERIFYING) text="Bytes checked";
310 : tmp=bytes_to_human(cntr->byte);
311 : if(text) print_detail2(text, cntr->byte, tmp, &x, col);
312 : }
313 : if(cntr->recvbyte)
314 : {
315 : const char *text=NULL;
316 : tmp=bytes_to_human(cntr->recvbyte);
317 : if(phase==STATUS_BACKUP) text="Bytes received";
318 : if(text) print_detail2(text, cntr->recvbyte, tmp, &x, col);
319 : }
320 : if(cntr->sentbyte)
321 : {
322 : const char *text=NULL;
323 : if(phase==STATUS_BACKUP) text="Bytes sent";
324 : else if(phase==STATUS_RESTORING) text="Bytes sent";
325 : tmp=bytes_to_human(cntr->sentbyte);
326 : print_detail2(text, cntr->sentbyte, tmp, &x, col);
327 : }
328 : if(p1cntr->start)
329 : {
330 : time_t now=0;
331 : time_t diff=0;
332 : now=time(NULL);
333 : diff=now-p1cntr->start;
334 :
335 : print_detail3("Start time", getdatestr(p1cntr->start), &x,col);
336 : print_detail3("Time taken", time_taken(diff), &x, col);
337 :
338 : if(diff>0)
339 : {
340 : uint64_t bytesleft=0;
341 : uint64_t byteswant=0;
342 : uint64_t bytesgot=0;
343 : float bytespersec=0;
344 : byteswant=p1cntr->byte;
345 : bytesgot=cntr->byte;
346 : bytespersec=(float)(bytesgot/diff);
347 : bytesleft=byteswant-bytesgot;
348 : if(bytespersec>0)
349 : {
350 : time_t timeleft=0;
351 : timeleft=(time_t)(bytesleft/bytespersec);
352 : print_detail3("Time left",
353 : time_taken(timeleft), &x, col);
354 : }
355 : }
356 : }
357 : if(path && *path)
358 : {
359 : #ifdef HAVE_NCURSES_H
360 : if(actg==ACTION_STATUS)
361 : {
362 : printw("\n%s\n", path);
363 : return;
364 : }
365 : #else
366 : printf("\n%s\n", path);
367 : #endif
368 : }
369 : }
370 : */
371 :
372 0 : static void screen_header(int row, int col)
373 : {
374 0 : int c=0;
375 0 : int l=0;
376 0 : const char *date=NULL;
377 0 : time_t t=time(NULL);
378 0 : date=getdatestr(t);
379 0 : l=strlen(date);
380 : #ifdef HAVE_NCURSES_H
381 0 : if(actg==ACTION_STATUS)
382 : {
383 0 : char v[32]="";
384 0 : snprintf(v, sizeof(v), " burp monitor %s", VERSION);
385 0 : print_line(v, 0-TOP_SPACE, col);
386 0 : mvprintw(0, col-l-1, date);
387 0 : return;
388 : }
389 : #endif
390 :
391 0 : printf("\n burp status");
392 :
393 0 : for(c=0; c<(int)(col-strlen(" burp status")-l-1); c++) printf(" ");
394 0 : printf("%s\n\n", date);
395 : }
396 :
397 0 : static int need_status(struct sel *sel)
398 : {
399 : static time_t lasttime=0;
400 0 : time_t now=0;
401 0 : time_t diff=0;
402 :
403 0 : if(sel->page==PAGE_VIEW_LOG && sel->llines) return 0;
404 :
405 : // Only ask for an update every second.
406 0 : now=time(NULL);
407 0 : diff=now-lasttime;
408 0 : if(diff<1)
409 : {
410 : // In case they fiddled their clock back in time.
411 0 : if(diff<0) lasttime=now;
412 0 : return 0;
413 : }
414 0 : lasttime=now;
415 0 : return 1;
416 : }
417 :
418 0 : static const char *logop_to_text(uint16_t logop)
419 : {
420 0 : switch(logop)
421 : {
422 0 : case BU_MANIFEST: return "Manifest";
423 0 : case BU_LOG_BACKUP: return "Backup log";
424 0 : case BU_LOG_RESTORE: return "Restore log";
425 0 : case BU_LOG_VERIFY: return "Verify log";
426 0 : case BU_STATS_BACKUP: return "Backup stats";
427 0 : case BU_STATS_RESTORE: return "Restore stats";
428 0 : case BU_STATS_VERIFY: return "Verify stats";
429 0 : default: return "";
430 : }
431 : }
432 :
433 0 : static void print_logs_list_line(struct sel *sel,
434 : uint16_t bit, int *x, int col)
435 : {
436 0 : char msg[64]="";
437 0 : if(!sel->backup || !(sel->backup->flags & bit)) return;
438 : snprintf(msg, sizeof(msg), "%s%s",
439 0 : *x==3?"Browse: ":" ", logop_to_text(bit));
440 0 : print_line(msg, (*x)++, col);
441 :
442 0 : if(!sel->logop) sel->logop=bit;
443 : #ifdef HAVE_NCURSES_H
444 0 : if(sel->logop==bit) mvprintw(*x+TOP_SPACE-1, 1, "*");
445 : #endif
446 : }
447 :
448 0 : static void client_and_status(struct sel *sel, int *x, int col)
449 : {
450 : char msg[1024];
451 0 : snprintf(msg, sizeof(msg), "Client: %s", sel->client->name);
452 : // sel->client->cntr->ent[CMD_FILE]->phase1,
453 : // sel->client->cntr->ent[CMD_FILE]->count);
454 0 : print_line(msg, (*x)++, col);
455 : snprintf(msg, sizeof(msg),
456 0 : "Status: %s", run_status_to_str(sel->client));
457 0 : print_line(msg, (*x)++, col);
458 0 : }
459 :
460 0 : static void client_and_status_and_backup(struct sel *sel, int *x, int col)
461 : {
462 : char msg[1024];
463 0 : client_and_status(sel, x, col);
464 0 : snprintf(msg, sizeof(msg), "Backup: %s", get_bu_str(sel->backup));
465 0 : print_line(msg, (*x)++, col);
466 0 : }
467 :
468 0 : static void client_and_status_and_backup_and_log(struct sel *sel,
469 : int *x, int col)
470 : {
471 : char msg[1024];
472 0 : client_and_status_and_backup(sel, x, col);
473 0 : snprintf(msg, sizeof(msg), "Browse: %s", logop_to_text(sel->logop));
474 0 : print_line(msg, (*x)++, col);
475 0 : }
476 :
477 : #ifdef HAVE_NCURSES_H
478 0 : static int selindex_from_cstat(struct sel *sel)
479 : {
480 0 : int selindex=0;
481 : struct cstat *c;
482 0 : for(c=sel->clist; c; c=c->next)
483 : {
484 0 : selindex++;
485 0 : if(sel->client==c) break;
486 : }
487 0 : return selindex;
488 : }
489 :
490 0 : static int selindex_from_bu(struct sel *sel)
491 : {
492 0 : int selindex=0;
493 : struct bu *b;
494 0 : for(b=sel->client->bu; b; b=b->next)
495 : {
496 0 : selindex++;
497 0 : if(sel->backup==b) break;
498 : }
499 0 : return selindex;
500 : }
501 :
502 0 : static int selindex_from_lline(struct sel *sel)
503 : {
504 0 : int selindex=0;
505 : struct lline *l;
506 0 : for(l=sel->llines; l; l=l->next)
507 : {
508 0 : selindex++;
509 0 : if(sel->lline==l) break;
510 : }
511 0 : return selindex;
512 : }
513 : #endif
514 :
515 0 : static void print_logs_list(struct sel *sel, int *x, int col)
516 : {
517 0 : print_logs_list_line(sel, BU_MANIFEST, x, col);
518 0 : print_logs_list_line(sel, BU_LOG_BACKUP, x, col);
519 0 : print_logs_list_line(sel, BU_LOG_RESTORE, x, col);
520 0 : print_logs_list_line(sel, BU_LOG_VERIFY, x, col);
521 0 : print_logs_list_line(sel, BU_STATS_BACKUP, x, col);
522 0 : print_logs_list_line(sel, BU_STATS_RESTORE, x, col);
523 0 : print_logs_list_line(sel, BU_STATS_VERIFY, x, col);
524 0 : }
525 :
526 0 : static void update_screen_clients(struct sel *sel, int *x, int col,
527 : int winmin, int winmax, struct conf **confs)
528 : {
529 : #ifdef HAVE_NCURSES_H
530 0 : int s=0;
531 : #endif
532 : struct cstat *c;
533 0 : int star_printed=0;
534 0 : int max_cname=28*((float)col/100);
535 : #ifdef HAVE_NCURSES_H
536 0 : if(actg==ACTION_STATUS_SNAPSHOT)
537 : #endif
538 : {
539 : size_t l;
540 0 : for(c=sel->clist; c; c=c->next)
541 0 : if((l=strlen(c->name))>(unsigned int)max_cname)
542 0 : max_cname=l;
543 : }
544 0 : for(c=sel->clist; c; c=c->next)
545 : {
546 : #ifdef HAVE_NCURSES_H
547 0 : if(actg==ACTION_STATUS)
548 : {
549 0 : s++;
550 0 : if(s<winmin) continue;
551 0 : if(s>winmax) break;
552 : }
553 : #endif
554 :
555 0 : client_summary(c, (*x)++, col, max_cname, confs);
556 :
557 : #ifdef HAVE_NCURSES_H
558 0 : if(actg==ACTION_STATUS && sel->client==c)
559 : {
560 0 : mvprintw((*x)+TOP_SPACE-1, 1, "*");
561 0 : star_printed=1;
562 : }
563 : #endif
564 : }
565 0 : if(!star_printed) sel->client=sel->clist;
566 0 : }
567 :
568 0 : static void update_screen_backups(struct sel *sel, int *x, int col,
569 : int winmin, int winmax)
570 : {
571 : #ifdef HAVE_NCURSES_H
572 0 : int s=0;
573 : #endif
574 : struct bu *b;
575 0 : char msg[1024]="";
576 0 : int star_printed=0;
577 0 : const char *extradesc=NULL;
578 0 : for(b=sel->client->bu; b; b=b->next)
579 : {
580 : #ifdef HAVE_NCURSES_H
581 0 : if(actg==ACTION_STATUS)
582 : {
583 0 : s++;
584 0 : if(s<winmin) continue;
585 0 : if(s>winmax) break;
586 : }
587 : #endif
588 :
589 0 : if(b->flags & BU_CURRENT)
590 0 : extradesc=" (current)";
591 0 : else if(b->flags & BU_WORKING)
592 0 : extradesc=" (working)";
593 0 : else if(b->flags & BU_FINISHING)
594 0 : extradesc=" (finishing)";
595 0 : else extradesc="";
596 :
597 : snprintf(msg, sizeof(msg), "%s %s%s",
598 0 : b==sel->client->bu?"Backup list:":
599 : " ",
600 : get_bu_str(b),
601 0 : extradesc);
602 0 : print_line(msg, (*x)++, col);
603 : #ifdef HAVE_NCURSES_H
604 0 : if(actg==ACTION_STATUS && sel->backup==b)
605 : {
606 0 : mvprintw((*x)+TOP_SPACE-1, 1, "*");
607 0 : star_printed=1;
608 : }
609 : #endif
610 : }
611 0 : if(!star_printed) sel->backup=sel->client->bu;
612 0 : }
613 :
614 0 : static void update_screen_live_counter_table(struct cntr_ent *e,
615 : int *x, int col)
616 : {
617 0 : if(!(e->flags & CNTR_TABULATE)) return;
618 : print_cntr_ent(e->label,
619 : e->count,
620 : e->changed,
621 : e->same,
622 : e->deleted,
623 : e->phase1,
624 0 : x, col);
625 : }
626 :
627 0 : static void update_screen_live_counter_single(struct cntr_ent *e,
628 : int *x, int col)
629 : {
630 0 : char msg[128]="";
631 0 : const char *bytes_human="";
632 0 : if(!(e->flags & CNTR_SINGLE_FIELD)) return;
633 0 : if(!e->count) return;
634 0 : switch(e->cmd)
635 : {
636 : case CMD_TIMESTAMP:
637 : case CMD_TIMESTAMP_END:
638 0 : return;
639 : case CMD_BYTES_ESTIMATED:
640 : case CMD_BYTES:
641 : case CMD_BYTES_RECV:
642 : case CMD_BYTES_SENT:
643 0 : bytes_human=bytes_to_human(e->count);
644 0 : break;
645 : default:
646 0 : break;
647 : }
648 : snprintf(msg, sizeof(msg), "%19s: %12"PRIu64" %s",
649 0 : e->label, e->count, bytes_human);
650 0 : print_line(msg, (*x)++, col);
651 : }
652 :
653 0 : static void update_screen_live_counters(struct cstat *client, int *x, int col)
654 : {
655 0 : char msg[128]="";
656 : struct cntr_ent *e;
657 0 : struct cntr *cntr=client->cntr;
658 0 : time_t start=(time_t)cntr->ent[(uint8_t)CMD_TIMESTAMP]->count;
659 0 : time_t end=(time_t)cntr->ent[(uint8_t)CMD_TIMESTAMP_END]->count;
660 0 : struct cntr_ent *gtotal=cntr->ent[(uint8_t)CMD_GRAND_TOTAL];
661 :
662 0 : print_line("", (*x)++, col);
663 0 : snprintf(msg, sizeof(msg), "Start time: %s", getdatestr(start));
664 0 : print_line(msg, (*x)++, col);
665 0 : snprintf(msg, sizeof(msg), " End time: %s", getdatestr(end));
666 0 : print_line(msg, (*x)++, col);
667 0 : snprintf(msg, sizeof(msg), "Time taken: %s", time_taken(end-start));
668 0 : print_line(msg, (*x)++, col);
669 0 : table_header(x, col);
670 0 : for(e=client->cntr->list; e; e=e->next)
671 0 : update_screen_live_counter_table(e, x, col);
672 0 : print_line("", (*x)++, col);
673 : snprintf(msg, sizeof(msg), "%19s: %"PRIu64"%%", "Percentage complete",
674 0 : ((gtotal->count+gtotal->same+gtotal->changed)*100)/gtotal->phase1);
675 0 : print_line(msg, (*x)++, col);
676 0 : print_line("", (*x)++, col);
677 0 : for(e=client->cntr->list; e; e=e->next)
678 0 : update_screen_live_counter_single(e, x, col);
679 0 : }
680 :
681 0 : static void update_screen_view_log(struct sel *sel, int *x, int col,
682 : int winmin, int winmax)
683 : {
684 : #ifdef HAVE_NCURSES_H
685 0 : int s=0;
686 : #endif
687 0 : int o=0;
688 : struct lline *l;
689 0 : const char *cp=NULL;
690 0 : int star_printed=0;
691 :
692 0 : if(sel->client
693 0 : && sel->backup
694 0 : && (sel->backup->flags & (BU_WORKING|BU_FINISHING))
695 0 : && (sel->logop & BU_STATS_BACKUP))
696 0 : return update_screen_live_counters(sel->client, x, col);
697 :
698 0 : for(l=sel->llines; l; l=l->next)
699 : {
700 : #ifdef HAVE_NCURSES_H
701 0 : if(actg==ACTION_STATUS)
702 : {
703 0 : s++;
704 0 : if(s<winmin) continue;
705 0 : if(s>winmax) break;
706 : }
707 : #endif
708 :
709 : // Allow them to scroll log lines left and right.
710 0 : for(cp=l->line, o=0; *cp && o<sel->offset; cp++, o++) { }
711 0 : print_line(cp, (*x)++, col);
712 :
713 : #ifdef HAVE_NCURSES_H
714 0 : if(actg==ACTION_STATUS && sel->lline==l)
715 : {
716 0 : mvprintw((*x)+TOP_SPACE-1, 1, "*");
717 0 : star_printed=1;
718 : }
719 : #endif
720 : }
721 0 : if(!star_printed) sel->lline=sel->llines;
722 : }
723 :
724 0 : static int update_screen(struct sel *sel, struct conf **confs)
725 : {
726 0 : int x=0;
727 0 : int row=24;
728 0 : int col=80;
729 : #ifdef HAVE_NCURSES_H
730 0 : int selindex=0;
731 : static int selindex_last=0;
732 : #endif
733 : static int winmin=0;
734 : static int winmax=0;
735 :
736 0 : screen_header(row, col);
737 :
738 : #ifdef HAVE_NCURSES_H
739 0 : if(actg==ACTION_STATUS)
740 : {
741 0 : getmaxyx(stdscr, row, col);
742 : //if(!winmax) winmax=row;
743 0 : switch(sel->page)
744 : {
745 : case PAGE_CLIENT_LIST:
746 0 : selindex=selindex_from_cstat(sel);
747 0 : break;
748 : case PAGE_BACKUP_LIST:
749 0 : selindex=selindex_from_bu(sel);
750 0 : break;
751 : case PAGE_BACKUP_LOGS:
752 0 : break;
753 : case PAGE_VIEW_LOG:
754 0 : selindex=selindex_from_lline(sel);
755 0 : break;
756 : }
757 : }
758 : #endif
759 0 : switch(sel->page)
760 : {
761 : case PAGE_CLIENT_LIST:
762 0 : break;
763 : case PAGE_BACKUP_LIST:
764 0 : client_and_status(sel, &x, col);
765 0 : break;
766 : case PAGE_BACKUP_LOGS:
767 0 : client_and_status_and_backup(sel, &x, col);
768 0 : break;
769 : case PAGE_VIEW_LOG:
770 0 : client_and_status_and_backup_and_log(sel, &x, col);
771 0 : break;
772 : }
773 :
774 : #ifdef HAVE_NCURSES_H
775 0 : if(actg==ACTION_STATUS)
776 : {
777 : // Adjust sliding window appropriately.
778 0 : if(selindex>selindex_last)
779 : {
780 0 : if(selindex>winmax-TOP_SPACE-1-x)
781 : {
782 0 : winmin+=selindex-selindex_last;
783 0 : winmax+=selindex-selindex_last;
784 : }
785 : }
786 0 : else if(selindex<selindex_last)
787 : {
788 0 : if(selindex<winmin)
789 : {
790 0 : winmin+=selindex-selindex_last;
791 0 : winmax+=selindex-selindex_last;
792 : }
793 : }
794 :
795 0 : if(winmin==winmax)
796 : {
797 0 : winmin=0;
798 0 : winmax=row;
799 : }
800 0 : else if(winmin<0)
801 : {
802 0 : winmin=0;
803 0 : winmax=row;
804 : }
805 : /*
806 : {
807 : char msg[64];
808 : snprintf(msg, sizeof(msg),
809 : "sel:%d si:%d min:%d max:%d %s\n",
810 : selindex, selindex_last, winmin, winmax,
811 : (selbu && *selbu && (*selbu)->prev)?
812 : (*selbu)->prev->timestamp:"");
813 : print_line(msg, -1, col);
814 : }
815 : */
816 : }
817 : #endif
818 :
819 0 : switch(sel->page)
820 : {
821 : case PAGE_CLIENT_LIST:
822 : update_screen_clients(sel, &x, col,
823 0 : winmin, winmax, confs);
824 0 : break;
825 : case PAGE_BACKUP_LIST:
826 : update_screen_backups(sel, &x, col,
827 0 : winmin, winmax);
828 0 : break;
829 : case PAGE_BACKUP_LOGS:
830 0 : print_logs_list(sel, &x, col);
831 0 : break;
832 : case PAGE_VIEW_LOG:
833 : update_screen_view_log(sel, &x, col,
834 0 : winmin, winmax);
835 0 : break;
836 : }
837 :
838 : #ifdef HAVE_NCURSES_H
839 0 : if(actg==ACTION_STATUS)
840 : {
841 : // Blank any remainder of the screen.
842 0 : for(; x<row; x++)
843 0 : print_line("", x, col);
844 0 : selindex_last=selindex;
845 : }
846 : #endif
847 0 : return 0;
848 : }
849 :
850 0 : static int request_status(struct asfd *asfd,
851 : const char *client, struct sel *sel, struct conf **confs)
852 : {
853 0 : char buf[256]="";
854 0 : switch(sel->page)
855 : {
856 : case PAGE_CLIENT_LIST:
857 0 : snprintf(buf, sizeof(buf), "c:\n");
858 0 : break;
859 : case PAGE_BACKUP_LIST:
860 0 : snprintf(buf, sizeof(buf), "c:%s\n", client);
861 0 : break;
862 : case PAGE_BACKUP_LOGS:
863 0 : if(sel->backup)
864 : snprintf(buf, sizeof(buf), "c:%s:b:%lu\n",
865 0 : client, sel->backup->bno);
866 0 : break;
867 : case PAGE_VIEW_LOG:
868 : {
869 0 : const char *lname=NULL;
870 0 : if(sel->logop & BU_LOG_BACKUP)
871 0 : lname="backup";
872 0 : else if(sel->logop & BU_LOG_RESTORE)
873 0 : lname="restore";
874 0 : else if(sel->logop & BU_LOG_VERIFY)
875 0 : lname="verify";
876 0 : else if(sel->logop & BU_MANIFEST)
877 0 : lname="manifest";
878 0 : else if(sel->logop & BU_STATS_BACKUP)
879 : {
880 : // Hack so that it does not request the logs for live
881 : // counters.
882 : // FIX THIS: need to do something similar for
883 : // restore/verify.
884 0 : if(!sel->backup) break;
885 0 : if(sel->client
886 0 : && sel->client->run_status==RUN_STATUS_RUNNING
887 0 : && sel->backup->flags
888 0 : & (BU_WORKING|BU_FINISHING))
889 : {
890 : // Make sure a request is sent, so that
891 : // the counters update.
892 : snprintf(buf, sizeof(buf),
893 : "c:%s:b:%lu\n",
894 0 : client, sel->backup->bno);
895 0 : break;
896 : }
897 : else
898 0 : lname="backup_stats";
899 : }
900 0 : else if(sel->logop & BU_STATS_RESTORE)
901 0 : lname="restore_stats";
902 0 : else if(sel->logop & BU_STATS_VERIFY)
903 0 : lname="verify_stats";
904 :
905 0 : if(sel->backup && lname)
906 : snprintf(buf, sizeof(buf), "c:%s:b:%lu:l:%s\n",
907 0 : client, sel->backup->bno, lname);
908 0 : break;
909 : }
910 : }
911 : /*
912 : if(confs->browsedir)
913 : snprintf(buf, sizeof(buf), "c:%s:b:%s:p:%s\n",
914 : client, confs->backup, confs->browsedir);
915 : else if(confs->browsefile)
916 : snprintf(buf, sizeof(buf), "c:%s:b:%s:f:%s\n",
917 : client, confs->backup, confs->browsefile);
918 : */
919 0 : if(*buf)
920 : {
921 0 : if(lfzp) logp("request: %s\n", buf);
922 0 : if(asfd->write_str(asfd, CMD_GEN /* ignored */, buf)) return -1;
923 : }
924 0 : return 0;
925 : }
926 :
927 0 : static void sighandler(int sig)
928 : {
929 : #ifdef HAVE_NCURSES_H
930 0 : if(actg==ACTION_STATUS) endwin();
931 : #endif
932 0 : logp("got signal: %d\n", sig);
933 0 : if(sig==SIGPIPE) logp("Server may have too many active status clients.\n");
934 0 : logp("exiting\n");
935 0 : exit(1);
936 : }
937 :
938 0 : static void setup_signals(void)
939 : {
940 0 : signal(SIGABRT, &sighandler);
941 0 : signal(SIGTERM, &sighandler);
942 0 : signal(SIGINT, &sighandler);
943 0 : signal(SIGPIPE, &sighandler);
944 0 : }
945 :
946 : #ifdef HAVE_NCURSES_H
947 0 : static void left(struct sel *sel)
948 : {
949 0 : switch(sel->page)
950 : {
951 : case PAGE_CLIENT_LIST:
952 0 : break;
953 : case PAGE_BACKUP_LIST:
954 0 : sel->page=PAGE_CLIENT_LIST;
955 0 : break;
956 : case PAGE_BACKUP_LOGS:
957 0 : sel->page=PAGE_BACKUP_LIST;
958 0 : break;
959 : case PAGE_VIEW_LOG:
960 0 : if(sel->offset>0)
961 : {
962 : // Allow log lines to be scrolled left.
963 0 : sel->offset--;
964 0 : break;
965 : }
966 0 : sel->page=PAGE_BACKUP_LOGS;
967 0 : llines_free(&sel->llines);
968 0 : sel->lline=NULL;
969 0 : break;
970 : }
971 0 : }
972 :
973 0 : static void right(struct sel *sel)
974 : {
975 0 : switch(sel->page)
976 : {
977 : case PAGE_CLIENT_LIST:
978 0 : sel->page=PAGE_BACKUP_LIST;
979 0 : break;
980 : case PAGE_BACKUP_LIST:
981 0 : sel->page=PAGE_BACKUP_LOGS;
982 0 : break;
983 : case PAGE_BACKUP_LOGS:
984 0 : if(lfzp) logp("Option selected: 0x%04X\n", sel->logop);
985 0 : sel->page=PAGE_VIEW_LOG;
986 0 : break;
987 : case PAGE_VIEW_LOG:
988 : // Allow log lines to be scrolled right.
989 0 : sel->offset++;
990 0 : break;
991 : }
992 0 : }
993 :
994 0 : static void up_client(struct sel *sel)
995 : {
996 0 : if(sel->client && sel->client->prev) sel->client=sel->client->prev;
997 0 : }
998 :
999 0 : static void down_client(struct sel *sel)
1000 : {
1001 0 : if(sel->client && sel->client->next) sel->client=sel->client->next;
1002 0 : }
1003 :
1004 0 : static void up_backup(struct sel *sel)
1005 : {
1006 0 : if(sel->backup && sel->backup->prev) sel->backup=sel->backup->prev;
1007 0 : }
1008 :
1009 0 : static void down_backup(struct sel *sel)
1010 : {
1011 0 : if(sel->backup && sel->backup->next) sel->backup=sel->backup->next;
1012 0 : }
1013 :
1014 0 : static void up_logs(struct sel *sel)
1015 : {
1016 0 : int i=0;
1017 0 : uint16_t sh=sel->logop;
1018 0 : for(i=0; sh>BU_MANIFEST && i<16; i++)
1019 : {
1020 0 : sh=sh>>1;
1021 0 : if(sh & sel->backup->flags)
1022 : {
1023 0 : sel->logop=sh;
1024 0 : break;
1025 : }
1026 : }
1027 0 : }
1028 :
1029 0 : static void down_logs(struct sel *sel)
1030 : {
1031 0 : int i=0;
1032 0 : uint16_t sh=sel->logop;
1033 0 : for(i=0; sh && i<16; i++)
1034 : {
1035 0 : sh=sh<<1;
1036 0 : if(sh & sel->backup->flags)
1037 : {
1038 0 : sel->logop=sh;
1039 0 : break;
1040 : }
1041 : }
1042 0 : }
1043 :
1044 0 : static void up_view_log(struct sel *sel)
1045 : {
1046 0 : if(sel->lline && sel->lline->prev) sel->lline=sel->lline->prev;
1047 0 : }
1048 :
1049 0 : static void down_view_log(struct sel *sel)
1050 : {
1051 0 : if(sel->lline && sel->lline->next) sel->lline=sel->lline->next;
1052 0 : }
1053 :
1054 0 : static void up(struct sel *sel)
1055 : {
1056 0 : switch(sel->page)
1057 : {
1058 : case PAGE_CLIENT_LIST:
1059 0 : up_client(sel);
1060 0 : break;
1061 : case PAGE_BACKUP_LIST:
1062 0 : up_backup(sel);
1063 0 : break;
1064 : case PAGE_BACKUP_LOGS:
1065 0 : up_logs(sel);
1066 0 : break;
1067 : case PAGE_VIEW_LOG:
1068 0 : up_view_log(sel);
1069 0 : break;
1070 : }
1071 0 : }
1072 :
1073 0 : static void down(struct sel *sel)
1074 : {
1075 0 : switch(sel->page)
1076 : {
1077 : case PAGE_CLIENT_LIST:
1078 0 : down_client(sel);
1079 0 : break;
1080 : case PAGE_BACKUP_LIST:
1081 0 : down_backup(sel);
1082 0 : break;
1083 : case PAGE_BACKUP_LOGS:
1084 0 : down_logs(sel);
1085 0 : break;
1086 : case PAGE_VIEW_LOG:
1087 0 : down_view_log(sel);
1088 0 : break;
1089 : }
1090 0 : }
1091 :
1092 0 : static void page_up_client(struct sel *sel, int row)
1093 : {
1094 : struct cstat *c;
1095 0 : for(c=sel->client; c; c=c->prev)
1096 : {
1097 0 : row--;
1098 0 : if(!row) break;
1099 : }
1100 0 : sel->client=c;
1101 0 : }
1102 :
1103 0 : static void page_down_client(struct sel *sel, int row)
1104 : {
1105 : struct cstat *c;
1106 0 : for(c=sel->client; c; c=c->next)
1107 : {
1108 0 : row--;
1109 0 : if(!row) break;
1110 0 : if(!c->next) break;
1111 : }
1112 0 : sel->client=c;
1113 0 : }
1114 :
1115 0 : static void page_up_backup(struct sel *sel, int row)
1116 : {
1117 : struct bu *b;
1118 0 : for(b=sel->backup; b; b=b->prev)
1119 : {
1120 0 : row--;
1121 0 : if(!row) break;
1122 : }
1123 0 : sel->backup=b;
1124 0 : }
1125 :
1126 0 : static void page_down_backup(struct sel *sel, int row)
1127 : {
1128 : struct bu *b;
1129 0 : for(b=sel->backup; b; b=b->next)
1130 : {
1131 0 : row--;
1132 0 : if(!row) break;
1133 0 : if(!b->next) break;
1134 : }
1135 0 : sel->backup=b;
1136 0 : }
1137 :
1138 0 : static void page_up(struct sel *sel)
1139 : {
1140 0 : int row=0;
1141 0 : int col=0;
1142 0 : getmaxyx(stdscr, row, col);
1143 0 : switch(sel->page)
1144 : {
1145 : case PAGE_CLIENT_LIST:
1146 0 : page_up_client(sel, row);
1147 0 : break;
1148 : case PAGE_BACKUP_LIST:
1149 0 : page_up_backup(sel, row);
1150 0 : break;
1151 : case PAGE_BACKUP_LOGS:
1152 0 : break;
1153 : case PAGE_VIEW_LOG:
1154 0 : break;
1155 : }
1156 0 : }
1157 :
1158 0 : static void page_down(struct sel *sel)
1159 : {
1160 0 : int row=0;
1161 0 : int col=0;
1162 0 : getmaxyx(stdscr, row, col);
1163 0 : switch(sel->page)
1164 : {
1165 : case PAGE_CLIENT_LIST:
1166 0 : page_down_client(sel, row);
1167 0 : break;
1168 : case PAGE_BACKUP_LIST:
1169 0 : page_down_backup(sel, row);
1170 0 : break;
1171 : case PAGE_BACKUP_LOGS:
1172 0 : break;
1173 : case PAGE_VIEW_LOG:
1174 0 : break;
1175 : }
1176 0 : }
1177 :
1178 0 : static int parse_stdin_data(struct asfd *asfd, struct sel *sel, int count)
1179 : {
1180 : static int ch;
1181 0 : if(asfd->rbuf->len!=sizeof(ch))
1182 : {
1183 : logp("Unexpected input length in %s: %d\n",
1184 0 : __func__, asfd->rbuf->len);
1185 0 : return -1;
1186 : }
1187 0 : memcpy(&ch, asfd->rbuf->buf, sizeof(ch));
1188 0 : switch(ch)
1189 : {
1190 : case 'q':
1191 : case 'Q':
1192 0 : return 1;
1193 : case 't':
1194 : case 'T':
1195 0 : if(toggle) toggle=0;
1196 0 : else toggle=1;
1197 0 : break;
1198 : case KEY_UP:
1199 : case 'k':
1200 : case 'K':
1201 0 : up(sel);
1202 0 : break;
1203 : case KEY_DOWN:
1204 : case 'j':
1205 : case 'J':
1206 0 : down(sel);
1207 0 : break;
1208 : case KEY_LEFT:
1209 : case 'h':
1210 : case 'H':
1211 0 : left(sel);
1212 0 : break;
1213 : case KEY_RIGHT:
1214 : case 'l':
1215 : case 'L':
1216 : case KEY_ENTER:
1217 : case '\n':
1218 : case ' ':
1219 0 : right(sel);
1220 0 : break;
1221 : case KEY_PPAGE:
1222 0 : page_up(sel);
1223 0 : break;
1224 : case KEY_NPAGE:
1225 0 : page_down(sel);
1226 0 : break;
1227 : case -1:
1228 0 : logp("Error on stdin\n");
1229 0 : return -1;
1230 : }
1231 :
1232 0 : return 0;
1233 : }
1234 : #endif
1235 :
1236 0 : static int parse_data(struct asfd *asfd, struct sel *sel, int count)
1237 : {
1238 : #ifdef HAVE_NCURSES_H
1239 0 : if(actg==ACTION_STATUS && asfd->streamtype==ASFD_STREAM_NCURSES_STDIN)
1240 0 : return parse_stdin_data(asfd, sel, count);
1241 : #endif
1242 0 : return json_input(asfd, sel);
1243 : }
1244 :
1245 0 : static int main_loop(struct async *as, enum action act, struct conf **confs)
1246 : {
1247 0 : int ret=-1;
1248 0 : char *client=NULL;
1249 0 : int count=0;
1250 0 : struct asfd *asfd=NULL;
1251 0 : struct asfd *sfd=as->asfd; // Server asfd.
1252 0 : int reqdone=0;
1253 0 : struct sel *sel=NULL;
1254 0 : const char *orig_client=get_string(confs[OPT_ORIG_CLIENT]);
1255 :
1256 0 : if(!(sel=(struct sel *)calloc_w(1, sizeof(struct sel), __func__)))
1257 0 : goto error;
1258 0 : sel->page=PAGE_CLIENT_LIST;
1259 :
1260 0 : if(orig_client && !client)
1261 : {
1262 0 : client=strdup_w(orig_client, __func__);
1263 0 : sel->page=PAGE_BACKUP_LIST;
1264 : }
1265 :
1266 : while(1)
1267 : {
1268 0 : if(need_status(sel) && !reqdone)
1269 : {
1270 0 : char *req=NULL;
1271 0 : if(sel->page>PAGE_CLIENT_LIST)
1272 : {
1273 0 : if(client) req=client;
1274 0 : else if(sel->client) req=sel->client->name;
1275 : }
1276 0 : if(request_status(sfd,
1277 0 : req, sel, confs)) goto error;
1278 0 : if(act==ACTION_STATUS_SNAPSHOT)
1279 0 : reqdone=1;
1280 : }
1281 :
1282 0 : if(as->read_write(as))
1283 : {
1284 : // FIX THIS - an exception is thrown when the console
1285 : // is resized.
1286 : /*
1287 : if(sfd->want_to_remove)
1288 : {
1289 : sfd->want_to_remove=0;
1290 : continue;
1291 : }
1292 : */
1293 0 : logp("Exiting main loop\n");
1294 0 : goto error;
1295 : }
1296 :
1297 0 : for(asfd=as->asfd; asfd; asfd=asfd->next)
1298 0 : while(asfd->rbuf->buf)
1299 : {
1300 0 : switch(parse_data(asfd, sel, count))
1301 : {
1302 0 : case 0: break;
1303 0 : case 1: goto end;
1304 0 : default: goto error;
1305 : }
1306 0 : iobuf_free_content(asfd->rbuf);
1307 0 : if(asfd->parse_readbuf(asfd))
1308 0 : goto error;
1309 : }
1310 :
1311 0 : if(!sel->client) sel->client=sel->clist;
1312 0 : if(!sel->backup && sel->client) sel->backup=sel->client->bu;
1313 :
1314 : #ifdef HAVE_NCURSES_H
1315 0 : if(act==ACTION_STATUS
1316 0 : && update_screen(sel, confs))
1317 0 : goto error;
1318 0 : refresh();
1319 : #endif
1320 :
1321 0 : if(act==ACTION_STATUS_SNAPSHOT
1322 0 : && sel->gotfirstresponse)
1323 : {
1324 0 : if(update_screen(sel, confs))
1325 0 : goto error;
1326 : // FIX THIS - should probably set up stdout with an
1327 : // asfd.
1328 0 : printf("\n");
1329 0 : break;
1330 : }
1331 : }
1332 :
1333 : end:
1334 0 : ret=0;
1335 : error:
1336 : // FIX THIS: should probably be freeing a bunch of stuff here.
1337 0 : free_v((void **)&sel);
1338 0 : return ret;
1339 : }
1340 :
1341 : #ifdef HAVE_NCURSES_H
1342 0 : static void ncurses_init(void)
1343 : {
1344 0 : initscr();
1345 0 : start_color();
1346 0 : use_default_colors();
1347 0 : raw();
1348 0 : keypad(stdscr, TRUE);
1349 0 : noecho();
1350 0 : curs_set(0);
1351 0 : halfdelay(3);
1352 : //nodelay(stdscr, TRUE);
1353 0 : }
1354 : #endif
1355 :
1356 0 : static pid_t fork_monitor(int *csin, int *csout, struct conf **confs)
1357 : {
1358 0 : int a=0;
1359 : char *args[12];
1360 :
1361 : // FIX THIS: get all args from configuration.
1362 0 : args[a++]=(char *)"/usr/sbin/burp";
1363 0 : args[a++]=(char *)"-c";
1364 0 : args[a++]=get_string(confs[OPT_CONFFILE]);
1365 0 : args[a++]=(char *)"-a";
1366 0 : args[a++]=(char *)"m";
1367 0 : args[a++]=NULL;
1368 :
1369 0 : return forkchild_fd(csin, csout, NULL, args[0], args);
1370 : }
1371 :
1372 0 : int status_client_ncurses(enum action act, struct conf **confs)
1373 : {
1374 0 : int csin=-1;
1375 0 : int csout=-1;
1376 0 : int ret=-1;
1377 0 : pid_t childpid=-1;
1378 0 : struct async *as=NULL;
1379 0 : const char *monitor_logfile=get_string(confs[OPT_MONITOR_LOGFILE]);
1380 :
1381 : #ifdef HAVE_NCURSES_H
1382 0 : actg=act; // So that the sighandler can call endwin().
1383 : #else
1384 : if(act==ACTION_STATUS)
1385 : {
1386 : printf("To use the live status monitor, you need to recompile with ncurses support.\n");
1387 : goto end;
1388 : }
1389 : #endif
1390 :
1391 0 : setup_signals();
1392 :
1393 : // Fork a burp child process that will contact the server over SSL.
1394 : // We will read and write from and to its stdout and stdin.
1395 0 : if((childpid=fork_monitor(&csin, &csout, confs))<0)
1396 0 : goto end;
1397 : //printf("childpid: %d\n", childpid);
1398 0 : set_non_blocking(csin);
1399 0 : set_non_blocking(csout);
1400 :
1401 0 : if(!(as=async_alloc())
1402 0 : || as->init(as, 0)
1403 0 : || !setup_asfd(as, "monitor stdin", &csin, NULL,
1404 0 : ASFD_STREAM_LINEBUF, ASFD_FD_CLIENT_MONITOR_WRITE, -1, confs)
1405 0 : || !setup_asfd(as, "monitor stdout", &csout, NULL,
1406 0 : ASFD_STREAM_LINEBUF, ASFD_FD_CLIENT_MONITOR_READ, -1, confs))
1407 0 : goto end;
1408 : //printf("ml: %s\n", monitor_logfile);
1409 : #ifdef HAVE_NCURSES_H
1410 0 : if(actg==ACTION_STATUS)
1411 : {
1412 0 : int stdinfd=fileno(stdin);
1413 0 : if(!setup_asfd(as, "stdin", &stdinfd, NULL,
1414 : ASFD_STREAM_NCURSES_STDIN, ASFD_FD_CLIENT_NCURSES_READ,
1415 0 : -1, confs))
1416 0 : goto end;
1417 0 : ncurses_init();
1418 : }
1419 : #endif
1420 0 : if(monitor_logfile
1421 0 : && !(lfzp=fzp_open(monitor_logfile, "wb")))
1422 0 : goto end;
1423 0 : log_fzp_set_direct(lfzp);
1424 :
1425 0 : ret=main_loop(as, act, confs);
1426 : end:
1427 : #ifdef HAVE_NCURSES_H
1428 0 : if(actg==ACTION_STATUS) endwin();
1429 : #endif
1430 0 : if(ret) logp("%s exiting with error: %d\n", __func__, ret);
1431 0 : fzp_close(&lfzp);
1432 0 : async_asfd_free_all(&as);
1433 0 : close_fd(&csin);
1434 0 : close_fd(&csout);
1435 0 : return ret;
1436 : }
|