int status_client_ncurses(struct config *conf, enum action act, const char *sclient) { int fd=0; int ret=0; int sel=0; char *rbuf=NULL; char buf[512]=""; int count=0; int details=0; char *last_rbuf=NULL; int srbr=0; char *client=NULL; int enterpressed=0; // int loop=0; int reqdone=0; #ifdef HAVE_NCURSES_H int stdinfd=fileno(stdin); actg=act; // So that the sighandler can call endwin(). #else if(act==ACTION_STATUS) { printf("To use the live status monitor, you need to recompile with ncurses support.\n"); return -1; } #endif setup_signals(); /* NULL == ::1 or 127.0.0.1 */ if((fd=init_client_socket(NULL, conf->status_port))<0) return -1; set_non_blocking(fd); #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { initscr(); start_color(); init_pair(1, COLOR_WHITE, COLOR_BLACK); init_pair(2, COLOR_WHITE, COLOR_BLACK); init_pair(3, COLOR_WHITE, COLOR_BLACK); raw(); keypad(stdscr, TRUE); noecho(); curs_set(0); halfdelay(3); //nodelay(stdscr, TRUE); } #endif #ifdef DBFP dbfp=fopen("/tmp/dbfp", "w"); #endif while(!ret) { int l; int mfd=-1; fd_set fsr; fd_set fse; struct timeval tval; // Failsafe to prevent the snapshot ever getting permanently // stuck. //if(act==ACTION_STATUS_SNAPSHOT && loop++>10000) // break; if(sclient && !client) { client=strdup(sclient); details=1; } if((enterpressed || need_status()) && !reqdone) { char *req=NULL; if(details && client) req=client; if(request_status(fd, req, conf)) { ret=-1; break; } enterpressed=0; if(act==ACTION_STATUS_SNAPSHOT) reqdone++; } FD_ZERO(&fsr); FD_ZERO(&fse); tval.tv_sec=1; tval.tv_usec=0; add_fd_to_sets(fd, &fsr, NULL, &fse, &mfd); #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) add_fd_to_sets(stdinfd, &fsr, NULL, &fse, &mfd); #endif if(select(mfd+1, &fsr, NULL, &fse, &tval)<0) { if(errno!=EAGAIN && errno!=EINTR) { logp("select error: %s\n", strerror(errno)); ret=-1; break; } continue; } if(FD_ISSET(fd, &fse)) { ret=-1; break; } #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { if(FD_ISSET(stdinfd, &fse)) { ret=-1; break; } if(FD_ISSET(stdinfd, &fsr)) { int quit=0; switch(getch()) { case 'q': case 'Q': quit++; break; case KEY_UP: case 'k': case 'K': if(details) break; sel--; break; case KEY_DOWN: case 'j': case 'J': if(details) break; sel++; break; case KEY_ENTER: case '\n': case ' ': if(details) details=0; else details++; enterpressed++; break; case KEY_LEFT: case 'h': case 'H': details=0; break; case KEY_RIGHT: case 'l': case 'L': details++; break; case KEY_NPAGE: { int row=0, col=0; getmaxyx(stdscr, row, col); sel+=row-TOP_SPACE; break; } case KEY_PPAGE: { int row=0, col=0; getmaxyx(stdscr, row, col); sel-=row-TOP_SPACE; break; } } if(quit) break; if(sel<0) sel=0; if(sel>=count) sel=count-1; // Attempt to print stuff to the screen right // now, to give the impression of key strokes // being responsive. if(!details && !sclient) { if((srbr=show_rbuf(last_rbuf, conf, sel, &client, &count, details, sclient))<0) { ret=-1; break; } if(!details) print_star(sel); refresh(); } } } #endif if(FD_ISSET(fd, &fsr)) { // ready to read. if((l=read(fd, buf, sizeof(buf)-1))>0) { size_t r=0; buf[l]='\0'; if(rbuf) r=strlen(rbuf); rbuf=(char *)realloc(rbuf, r+l+1); if(!r) *rbuf='\0'; strcat(rbuf+r, buf); } else break; if(act==ACTION_STATUS_SNAPSHOT) { if(rbuf) { if(!strcmp(rbuf, "\n")) { // This happens when there are // no backup clients. break; } if(strstr(rbuf, "\n-list end-\n")) { printf("%s", rbuf); break; } } continue; } //if(rbuf) printf("rbuf: %s\n", rbuf); /* if(l<0) { ret=-1; break; } */ } if((srbr=show_rbuf(rbuf, conf, sel, &client, &count, details, sclient))<0) { ret=-1; break; } else if(srbr) { // Remember it, so that we can present the detailed // screen without delay, above. if(last_rbuf) free(last_rbuf); last_rbuf=rbuf; rbuf=NULL; } if(sclient) details++; usleep(20000); #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) { flushinp(); continue; } #endif if(count) { printf("\n"); break; } } #ifdef HAVE_NCURSES_H if(actg==ACTION_STATUS) endwin(); #endif close_fd(&fd); if(last_rbuf) free(last_rbuf); if(rbuf) free(rbuf); #ifdef DBFP if(dbfp) fclose(dbfp); #endif return ret; }
static #endif int status_client_ncurses_main_loop(struct async *as, struct asfd *so_asfd, struct sel *sel, const char *orig_client) { int ret=-1; char *client=NULL; int count=0; struct asfd *asfd=NULL; struct asfd *sfd=NULL; // Server asfd. int reqdone=0; if(!sel || !as || !(stdout_asfd=so_asfd) || !(sfd=as->asfd)) { logp("parameters not set up correctly in %s\n", __func__); goto error; } sel->page=PAGE_CLIENT_LIST; if(orig_client) { client=strdup_w(orig_client, __func__); sel->page=PAGE_BACKUP_LIST; } if(json_input_init()) goto end; while(1) { if(need_status(sel) && !reqdone) { char *req=NULL; if(sel->page>PAGE_CLIENT_LIST) { if(client) req=client; else if(sel->client) req=sel->client->name; } if(request_status(sfd, req, sel)) goto error; // We only want to start on the client the user gave to // us. Freeing it will allow the user to browse other // clients thereafter. free_w(&client); if(actg==ACTION_STATUS_SNAPSHOT) reqdone=1; } if(as->read_write(as)) { // FIX THIS - an exception is thrown when the console // is resized. /* if(sfd->want_to_remove) { sfd->want_to_remove=0; continue; } */ logp("Exiting main loop\n"); goto error; } for(asfd=as->asfd; asfd; asfd=asfd->next) { while(asfd->rbuf->buf) { switch(parse_data(asfd, sel, count)) { case 0: break; case 1: goto end; default: goto error; } iobuf_free_content(asfd->rbuf); if(asfd->parse_readbuf(asfd)) goto error; } // Select things if they are not already selected. if(sel->client) { if(!sel->backup) sel->backup=sel->client->bu; } else sel->client=sel->clist; } #ifdef HAVE_NCURSES if(actg==ACTION_STATUS && update_screen(sel)) goto error; refresh(); #endif if(actg==ACTION_STATUS_SNAPSHOT && sel->client) { if(update_screen(sel)) goto error; stdout_asfd->write_str(stdout_asfd, CMD_GEN, "\n"); break; } } end: ret=0; error: json_input_free(); return ret; }
static int main_loop(struct async *as, enum action act, struct conf **confs) { int ret=-1; char *client=NULL; int count=0; struct asfd *asfd=NULL; struct asfd *sfd=as->asfd; // Server asfd. int reqdone=0; struct sel *sel=NULL; const char *orig_client=get_string(confs[OPT_ORIG_CLIENT]); if(!(sel=(struct sel *)calloc_w(1, sizeof(struct sel), __func__))) goto error; sel->page=PAGE_CLIENT_LIST; if(orig_client && !client) { client=strdup_w(orig_client, __func__); sel->page=PAGE_BACKUP_LIST; } while(1) { if(need_status(sel) && !reqdone) { char *req=NULL; if(sel->page>PAGE_CLIENT_LIST) { if(client) req=client; else if(sel->client) req=sel->client->name; } if(request_status(sfd, req, sel, confs)) goto error; if(act==ACTION_STATUS_SNAPSHOT) reqdone=1; } if(as->read_write(as)) { // FIX THIS - an exception is thrown when the console // is resized. /* if(sfd->want_to_remove) { sfd->want_to_remove=0; continue; } */ logp("Exiting main loop\n"); goto error; } for(asfd=as->asfd; asfd; asfd=asfd->next) while(asfd->rbuf->buf) { switch(parse_data(asfd, sel, count)) { case 0: break; case 1: goto end; default: goto error; } iobuf_free_content(asfd->rbuf); if(asfd->parse_readbuf(asfd)) goto error; } if(!sel->client) sel->client=sel->clist; if(!sel->backup && sel->client) sel->backup=sel->client->bu; #ifdef HAVE_NCURSES_H if(act==ACTION_STATUS && update_screen(sel, confs)) goto error; refresh(); #endif if(act==ACTION_STATUS_SNAPSHOT && sel->gotfirstresponse) { if(update_screen(sel, confs)) goto error; // FIX THIS - should probably set up stdout with an // asfd. printf("\n"); break; } } end: ret=0; error: // FIX THIS: should probably be freeing a bunch of stuff here. free_v((void **)&sel); return ret; }