1*ea37671dSMatthew Dillon /* 2*ea37671dSMatthew Dillon * Copyright (c) 2019 The DragonFly Project. All rights reserved. 3*ea37671dSMatthew Dillon * 4*ea37671dSMatthew Dillon * This code is derived from software contributed to The DragonFly Project 5*ea37671dSMatthew Dillon * by Matthew Dillon <dillon@backplane.com> 6*ea37671dSMatthew Dillon * 7*ea37671dSMatthew Dillon * This code uses concepts and configuration based on 'synth', by 8*ea37671dSMatthew Dillon * John R. Marino <draco@marino.st>, which was written in ada. 9*ea37671dSMatthew Dillon * 10*ea37671dSMatthew Dillon * Redistribution and use in source and binary forms, with or without 11*ea37671dSMatthew Dillon * modification, are permitted provided that the following conditions 12*ea37671dSMatthew Dillon * are met: 13*ea37671dSMatthew Dillon * 14*ea37671dSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 15*ea37671dSMatthew Dillon * notice, this list of conditions and the following disclaimer. 16*ea37671dSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 17*ea37671dSMatthew Dillon * notice, this list of conditions and the following disclaimer in 18*ea37671dSMatthew Dillon * the documentation and/or other materials provided with the 19*ea37671dSMatthew Dillon * distribution. 20*ea37671dSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 21*ea37671dSMatthew Dillon * contributors may be used to endorse or promote products derived 22*ea37671dSMatthew Dillon * from this software without specific, prior written permission. 23*ea37671dSMatthew Dillon * 24*ea37671dSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25*ea37671dSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26*ea37671dSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27*ea37671dSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28*ea37671dSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29*ea37671dSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 30*ea37671dSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31*ea37671dSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32*ea37671dSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33*ea37671dSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 34*ea37671dSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35*ea37671dSMatthew Dillon * SUCH DAMAGE. 36*ea37671dSMatthew Dillon */ 37*ea37671dSMatthew Dillon #include "dsynth.h" 38*ea37671dSMatthew Dillon 39*ea37671dSMatthew Dillon #include <curses.h> 40*ea37671dSMatthew Dillon 41*ea37671dSMatthew Dillon /* 42*ea37671dSMatthew Dillon * ncurses - LINES, COLS are the main things we care about 43*ea37671dSMatthew Dillon */ 44*ea37671dSMatthew Dillon static WINDOW *CWin; 45*ea37671dSMatthew Dillon static WINDOW *CMon; 46*ea37671dSMatthew Dillon static const char *Line0 = " Total - Built - Ignored - " 47*ea37671dSMatthew Dillon "Load - Pkg/hour - "; 48*ea37671dSMatthew Dillon static const char *Line1 = " Left - Failed - Skipped - " 49*ea37671dSMatthew Dillon "Swap - Impulse - --:--:-- "; 50*ea37671dSMatthew Dillon static const char *LineB = "===========================================" 51*ea37671dSMatthew Dillon "===================================="; 52*ea37671dSMatthew Dillon static const char *LineI = " ID Duration Build Phase Origin " 53*ea37671dSMatthew Dillon " Lines"; 54*ea37671dSMatthew Dillon 55*ea37671dSMatthew Dillon static int LastReduce; 56*ea37671dSMatthew Dillon static off_t MonitorLogOff; 57*ea37671dSMatthew Dillon static int MonitorLogLines; 58*ea37671dSMatthew Dillon static int MonitorBufBeg; 59*ea37671dSMatthew Dillon static int MonitorBufEnd; 60*ea37671dSMatthew Dillon static int MonitorBufScan; 61*ea37671dSMatthew Dillon static int MonitorBufDiscardMode; 62*ea37671dSMatthew Dillon static char MonitorBuf[1024]; 63*ea37671dSMatthew Dillon 64*ea37671dSMatthew Dillon static int guireadline(int fd, char **bufp); 65*ea37671dSMatthew Dillon 66*ea37671dSMatthew Dillon #define TOTAL_COL 7 67*ea37671dSMatthew Dillon #define BUILT_COL 21 68*ea37671dSMatthew Dillon #define IGNORED_COL 36 69*ea37671dSMatthew Dillon #define LOAD_COL 48 70*ea37671dSMatthew Dillon #define GPKGRATE_COL 64 71*ea37671dSMatthew Dillon #define REDUCE_COL 71 72*ea37671dSMatthew Dillon 73*ea37671dSMatthew Dillon #define LEFT_COL 7 74*ea37671dSMatthew Dillon #define FAILED_COL 21 75*ea37671dSMatthew Dillon #define SKIPPED_COL 36 76*ea37671dSMatthew Dillon #define SWAP_COL 48 77*ea37671dSMatthew Dillon #define IMPULSE_COL 64 78*ea37671dSMatthew Dillon #define TIME_COL 71 79*ea37671dSMatthew Dillon 80*ea37671dSMatthew Dillon #define ID_COL 1 81*ea37671dSMatthew Dillon #define DURATION_COL 5 82*ea37671dSMatthew Dillon #define BUILD_PHASE_COL 15 83*ea37671dSMatthew Dillon #define ORIGIN_COL 32 84*ea37671dSMatthew Dillon #define LINES_COL 73 85*ea37671dSMatthew Dillon 86*ea37671dSMatthew Dillon /* 87*ea37671dSMatthew Dillon * The row that the worker list starts on, and the row that the log starts 88*ea37671dSMatthew Dillon * on. 89*ea37671dSMatthew Dillon */ 90*ea37671dSMatthew Dillon #define WORKER_START 5 91*ea37671dSMatthew Dillon #define LOG_START (WORKER_START + MaxWorkers + 1) 92*ea37671dSMatthew Dillon 93*ea37671dSMatthew Dillon static void NCursesReset(void); 94*ea37671dSMatthew Dillon 95*ea37671dSMatthew Dillon static void 96*ea37671dSMatthew Dillon NCursesInit(void) 97*ea37671dSMatthew Dillon { 98*ea37671dSMatthew Dillon if (UseNCurses == 0) 99*ea37671dSMatthew Dillon return; 100*ea37671dSMatthew Dillon 101*ea37671dSMatthew Dillon CWin = initscr(); 102*ea37671dSMatthew Dillon NCursesReset(); 103*ea37671dSMatthew Dillon 104*ea37671dSMatthew Dillon intrflush(stdscr, FALSE); 105*ea37671dSMatthew Dillon nonl(); 106*ea37671dSMatthew Dillon noecho(); 107*ea37671dSMatthew Dillon cbreak(); 108*ea37671dSMatthew Dillon 109*ea37671dSMatthew Dillon start_color(); 110*ea37671dSMatthew Dillon use_default_colors(); 111*ea37671dSMatthew Dillon init_pair(1, COLOR_RED, -1); 112*ea37671dSMatthew Dillon init_pair(2, COLOR_GREEN, -1); 113*ea37671dSMatthew Dillon init_pair(3, -1, -1); 114*ea37671dSMatthew Dillon } 115*ea37671dSMatthew Dillon 116*ea37671dSMatthew Dillon static void 117*ea37671dSMatthew Dillon NCursesReset(void) 118*ea37671dSMatthew Dillon { 119*ea37671dSMatthew Dillon int i; 120*ea37671dSMatthew Dillon 121*ea37671dSMatthew Dillon if (UseNCurses == 0) 122*ea37671dSMatthew Dillon return; 123*ea37671dSMatthew Dillon 124*ea37671dSMatthew Dillon if (CMon) { 125*ea37671dSMatthew Dillon delwin(CMon); 126*ea37671dSMatthew Dillon CMon = NULL; 127*ea37671dSMatthew Dillon } 128*ea37671dSMatthew Dillon 129*ea37671dSMatthew Dillon werase(CWin); 130*ea37671dSMatthew Dillon curs_set(0); 131*ea37671dSMatthew Dillon redrawwin(CWin); 132*ea37671dSMatthew Dillon wrefresh(CWin); 133*ea37671dSMatthew Dillon mvwprintw(CWin, 0, 0, "%s", Line0); 134*ea37671dSMatthew Dillon mvwprintw(CWin, 1, 0, "%s", Line1); 135*ea37671dSMatthew Dillon mvwprintw(CWin, 2, 0, "%s", LineB); 136*ea37671dSMatthew Dillon mvwprintw(CWin, 3, 0, "%s", LineI); 137*ea37671dSMatthew Dillon mvwprintw(CWin, 4, 0, "%s", LineB); 138*ea37671dSMatthew Dillon 139*ea37671dSMatthew Dillon for (i = 0; i < MaxWorkers; ++i) { 140*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, ID_COL, "%02d", i); 141*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, DURATION_COL, "--:--:--"); 142*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, BUILD_PHASE_COL, "Idle"); 143*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, ORIGIN_COL, "%39.39s", ""); 144*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, LINES_COL, "%6.6s", ""); 145*ea37671dSMatthew Dillon } 146*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + MaxWorkers, 0, "%s", LineB); 147*ea37671dSMatthew Dillon wrefresh(CWin); 148*ea37671dSMatthew Dillon 149*ea37671dSMatthew Dillon CMon = subwin(CWin, 0, 0, LOG_START, 0); 150*ea37671dSMatthew Dillon scrollok(CMon, 1); 151*ea37671dSMatthew Dillon MonitorLogLines = LINES - LOG_START; 152*ea37671dSMatthew Dillon MonitorLogOff = 0; 153*ea37671dSMatthew Dillon MonitorBufBeg = 0; 154*ea37671dSMatthew Dillon MonitorBufEnd = 0; 155*ea37671dSMatthew Dillon MonitorBufScan = 0; 156*ea37671dSMatthew Dillon MonitorBufDiscardMode = 0; 157*ea37671dSMatthew Dillon nodelay(CMon, 1); 158*ea37671dSMatthew Dillon 159*ea37671dSMatthew Dillon LastReduce = -1; 160*ea37671dSMatthew Dillon } 161*ea37671dSMatthew Dillon 162*ea37671dSMatthew Dillon static void 163*ea37671dSMatthew Dillon NCursesUpdateTop(topinfo_t *info) 164*ea37671dSMatthew Dillon { 165*ea37671dSMatthew Dillon if (UseNCurses == 0) 166*ea37671dSMatthew Dillon return; 167*ea37671dSMatthew Dillon 168*ea37671dSMatthew Dillon mvwprintw(CWin, 0, TOTAL_COL, "%-5d", info->total); 169*ea37671dSMatthew Dillon mvwprintw(CWin, 0, BUILT_COL, "%-5d", info->successful); 170*ea37671dSMatthew Dillon mvwprintw(CWin, 0, IGNORED_COL, "%-5d", info->ignored); 171*ea37671dSMatthew Dillon if (info->dload[0] > 999.9) 172*ea37671dSMatthew Dillon mvwprintw(CWin, 0, LOAD_COL, "%5.0f", info->dload[0]); 173*ea37671dSMatthew Dillon else 174*ea37671dSMatthew Dillon mvwprintw(CWin, 0, LOAD_COL, "%5.1f", info->dload[0]); 175*ea37671dSMatthew Dillon mvwprintw(CWin, 0, GPKGRATE_COL, "%-5d", info->pkgrate); 176*ea37671dSMatthew Dillon 177*ea37671dSMatthew Dillon /* 178*ea37671dSMatthew Dillon * If dynamic worker reduction is active include a field, 179*ea37671dSMatthew Dillon * Otherwise blank the field. 180*ea37671dSMatthew Dillon */ 181*ea37671dSMatthew Dillon if (LastReduce != DynamicMaxWorkers) { 182*ea37671dSMatthew Dillon LastReduce = DynamicMaxWorkers; 183*ea37671dSMatthew Dillon if (MaxWorkers == LastReduce) 184*ea37671dSMatthew Dillon mvwprintw(CWin, 0, REDUCE_COL, " "); 185*ea37671dSMatthew Dillon else 186*ea37671dSMatthew Dillon mvwprintw(CWin, 0, REDUCE_COL, "Limit %-2d", 187*ea37671dSMatthew Dillon LastReduce); 188*ea37671dSMatthew Dillon } 189*ea37671dSMatthew Dillon 190*ea37671dSMatthew Dillon mvwprintw(CWin, 1, LEFT_COL, "%-5d", info->remaining); 191*ea37671dSMatthew Dillon mvwprintw(CWin, 1, FAILED_COL, "%-5d", info->failed); 192*ea37671dSMatthew Dillon mvwprintw(CWin, 1, SKIPPED_COL, "%-5d", info->skipped); 193*ea37671dSMatthew Dillon if (info->noswap) 194*ea37671dSMatthew Dillon mvwprintw(CWin, 1, SWAP_COL, "- "); 195*ea37671dSMatthew Dillon else 196*ea37671dSMatthew Dillon mvwprintw(CWin, 1, SWAP_COL, "%5.1f", info->dswap); 197*ea37671dSMatthew Dillon mvwprintw(CWin, 1, IMPULSE_COL, "%-5d", info->pkgimpulse); 198*ea37671dSMatthew Dillon if (info->h > 99) 199*ea37671dSMatthew Dillon mvwprintw(CWin, 1, TIME_COL-1, "%3d:%02d:%02d", 200*ea37671dSMatthew Dillon info->h, info->m, info->s); 201*ea37671dSMatthew Dillon else 202*ea37671dSMatthew Dillon mvwprintw(CWin, 1, TIME_COL, "%02d:%02d:%02d", 203*ea37671dSMatthew Dillon info->h, info->m, info->s); 204*ea37671dSMatthew Dillon } 205*ea37671dSMatthew Dillon 206*ea37671dSMatthew Dillon static void 207*ea37671dSMatthew Dillon NCursesUpdateLogs(void) 208*ea37671dSMatthew Dillon { 209*ea37671dSMatthew Dillon int fd = dlog00_fd(); 210*ea37671dSMatthew Dillon char *ptr; 211*ea37671dSMatthew Dillon char c; 212*ea37671dSMatthew Dillon ssize_t n; 213*ea37671dSMatthew Dillon int w; 214*ea37671dSMatthew Dillon 215*ea37671dSMatthew Dillon if (UseNCurses == 0) 216*ea37671dSMatthew Dillon return; 217*ea37671dSMatthew Dillon 218*ea37671dSMatthew Dillon for (;;) { 219*ea37671dSMatthew Dillon n = guireadline(fd, &ptr); 220*ea37671dSMatthew Dillon if (n < 0) 221*ea37671dSMatthew Dillon break; 222*ea37671dSMatthew Dillon if (n == 0) 223*ea37671dSMatthew Dillon continue; 224*ea37671dSMatthew Dillon 225*ea37671dSMatthew Dillon /* 226*ea37671dSMatthew Dillon * Scroll down 227*ea37671dSMatthew Dillon */ 228*ea37671dSMatthew Dillon if (n > COLS) 229*ea37671dSMatthew Dillon w = COLS; 230*ea37671dSMatthew Dillon else 231*ea37671dSMatthew Dillon w = n; 232*ea37671dSMatthew Dillon c = ptr[w]; 233*ea37671dSMatthew Dillon ptr[w] = 0; 234*ea37671dSMatthew Dillon 235*ea37671dSMatthew Dillon /* 236*ea37671dSMatthew Dillon * Filter out these logs from the display (they remain in 237*ea37671dSMatthew Dillon * the 00*.log file) to reduce clutter. 238*ea37671dSMatthew Dillon */ 239*ea37671dSMatthew Dillon if (strncmp(ptr, "[XXX] Load=", 11) == 0) 240*ea37671dSMatthew Dillon continue; 241*ea37671dSMatthew Dillon 242*ea37671dSMatthew Dillon /* 243*ea37671dSMatthew Dillon * Output possibly colored log line 244*ea37671dSMatthew Dillon */ 245*ea37671dSMatthew Dillon wscrl(CMon, -1); 246*ea37671dSMatthew Dillon if (strstr(ptr, "] SUCCESS ")) { 247*ea37671dSMatthew Dillon wattrset(CMon, COLOR_PAIR(2)); 248*ea37671dSMatthew Dillon } else if (strstr(ptr, "] FAILURE ")) { 249*ea37671dSMatthew Dillon wattrset(CMon, COLOR_PAIR(1)); 250*ea37671dSMatthew Dillon } 251*ea37671dSMatthew Dillon mvwprintw(CMon, 0, 0, "%s", ptr); 252*ea37671dSMatthew Dillon ptr[w] = c; 253*ea37671dSMatthew Dillon wattrset(CMon, COLOR_PAIR(3)); 254*ea37671dSMatthew Dillon } 255*ea37671dSMatthew Dillon } 256*ea37671dSMatthew Dillon 257*ea37671dSMatthew Dillon static void 258*ea37671dSMatthew Dillon NCursesUpdate(worker_t *work) 259*ea37671dSMatthew Dillon { 260*ea37671dSMatthew Dillon const char *phase; 261*ea37671dSMatthew Dillon const char *origin; 262*ea37671dSMatthew Dillon time_t t; 263*ea37671dSMatthew Dillon int i = work->index; 264*ea37671dSMatthew Dillon int h; 265*ea37671dSMatthew Dillon int m; 266*ea37671dSMatthew Dillon int s; 267*ea37671dSMatthew Dillon 268*ea37671dSMatthew Dillon if (UseNCurses == 0) 269*ea37671dSMatthew Dillon return; 270*ea37671dSMatthew Dillon 271*ea37671dSMatthew Dillon phase = "Unknown"; 272*ea37671dSMatthew Dillon origin = ""; 273*ea37671dSMatthew Dillon 274*ea37671dSMatthew Dillon switch(work->state) { 275*ea37671dSMatthew Dillon case WORKER_NONE: 276*ea37671dSMatthew Dillon phase = "None"; 277*ea37671dSMatthew Dillon /* fall through */ 278*ea37671dSMatthew Dillon case WORKER_IDLE: 279*ea37671dSMatthew Dillon if (work->state == WORKER_IDLE) 280*ea37671dSMatthew Dillon phase = "Idle"; 281*ea37671dSMatthew Dillon /* fall through */ 282*ea37671dSMatthew Dillon case WORKER_FAILED: 283*ea37671dSMatthew Dillon if (work->state == WORKER_FAILED) 284*ea37671dSMatthew Dillon phase = "Failed"; 285*ea37671dSMatthew Dillon /* fall through */ 286*ea37671dSMatthew Dillon case WORKER_EXITING: 287*ea37671dSMatthew Dillon if (work->state == WORKER_EXITING) 288*ea37671dSMatthew Dillon phase = "Exiting"; 289*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, DURATION_COL, 290*ea37671dSMatthew Dillon "--:--:--"); 291*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, BUILD_PHASE_COL, 292*ea37671dSMatthew Dillon "%-16.16s", phase); 293*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, ORIGIN_COL, 294*ea37671dSMatthew Dillon "%-39.39s", ""); 295*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, LINES_COL, 296*ea37671dSMatthew Dillon "%-6.6s", ""); 297*ea37671dSMatthew Dillon return; 298*ea37671dSMatthew Dillon case WORKER_PENDING: 299*ea37671dSMatthew Dillon phase = "Pending"; 300*ea37671dSMatthew Dillon break; 301*ea37671dSMatthew Dillon case WORKER_RUNNING: 302*ea37671dSMatthew Dillon phase = "Running"; 303*ea37671dSMatthew Dillon break; 304*ea37671dSMatthew Dillon case WORKER_DONE: 305*ea37671dSMatthew Dillon phase = "Done"; 306*ea37671dSMatthew Dillon break; 307*ea37671dSMatthew Dillon case WORKER_FROZEN: 308*ea37671dSMatthew Dillon phase = "FROZEN"; 309*ea37671dSMatthew Dillon break; 310*ea37671dSMatthew Dillon default: 311*ea37671dSMatthew Dillon break; 312*ea37671dSMatthew Dillon } 313*ea37671dSMatthew Dillon 314*ea37671dSMatthew Dillon t = time(NULL) - work->start_time; 315*ea37671dSMatthew Dillon s = t % 60; 316*ea37671dSMatthew Dillon m = t / 60 % 60; 317*ea37671dSMatthew Dillon h = t / 60 / 60; 318*ea37671dSMatthew Dillon 319*ea37671dSMatthew Dillon if (work->state == WORKER_RUNNING) 320*ea37671dSMatthew Dillon phase = getphasestr(work->phase); 321*ea37671dSMatthew Dillon 322*ea37671dSMatthew Dillon if (work->pkg) 323*ea37671dSMatthew Dillon origin = work->pkg->portdir; 324*ea37671dSMatthew Dillon else 325*ea37671dSMatthew Dillon origin = ""; 326*ea37671dSMatthew Dillon 327*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, DURATION_COL, 328*ea37671dSMatthew Dillon "%02d:%02d:%02d", h, m, s); 329*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, BUILD_PHASE_COL, 330*ea37671dSMatthew Dillon "%-16.16s", phase); 331*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, ORIGIN_COL, 332*ea37671dSMatthew Dillon "%-39.39s", origin); 333*ea37671dSMatthew Dillon mvwprintw(CWin, WORKER_START + i, LINES_COL, 334*ea37671dSMatthew Dillon "%6d", work->lines); 335*ea37671dSMatthew Dillon } 336*ea37671dSMatthew Dillon 337*ea37671dSMatthew Dillon static void 338*ea37671dSMatthew Dillon NCursesSync(void) 339*ea37671dSMatthew Dillon { 340*ea37671dSMatthew Dillon int c; 341*ea37671dSMatthew Dillon 342*ea37671dSMatthew Dillon if (UseNCurses == 0) 343*ea37671dSMatthew Dillon return; 344*ea37671dSMatthew Dillon 345*ea37671dSMatthew Dillon while ((c = wgetch(CMon)) != ERR) { 346*ea37671dSMatthew Dillon if (c == KEY_RESIZE) 347*ea37671dSMatthew Dillon NCursesReset(); 348*ea37671dSMatthew Dillon } 349*ea37671dSMatthew Dillon wrefresh(CWin); 350*ea37671dSMatthew Dillon wrefresh(CMon); 351*ea37671dSMatthew Dillon } 352*ea37671dSMatthew Dillon 353*ea37671dSMatthew Dillon static void 354*ea37671dSMatthew Dillon NCursesDone(void) 355*ea37671dSMatthew Dillon { 356*ea37671dSMatthew Dillon if (UseNCurses == 0) 357*ea37671dSMatthew Dillon return; 358*ea37671dSMatthew Dillon 359*ea37671dSMatthew Dillon endwin(); 360*ea37671dSMatthew Dillon } 361*ea37671dSMatthew Dillon 362*ea37671dSMatthew Dillon static int 363*ea37671dSMatthew Dillon guireadline(int fd, char **bufp) 364*ea37671dSMatthew Dillon { 365*ea37671dSMatthew Dillon int r; 366*ea37671dSMatthew Dillon int n; 367*ea37671dSMatthew Dillon 368*ea37671dSMatthew Dillon /* 369*ea37671dSMatthew Dillon * Reset buffer as an optimization to avoid unnecessary 370*ea37671dSMatthew Dillon * shifts. 371*ea37671dSMatthew Dillon */ 372*ea37671dSMatthew Dillon *bufp = NULL; 373*ea37671dSMatthew Dillon if (MonitorBufBeg == MonitorBufEnd) { 374*ea37671dSMatthew Dillon MonitorBufBeg = 0; 375*ea37671dSMatthew Dillon MonitorBufEnd = 0; 376*ea37671dSMatthew Dillon MonitorBufScan = 0; 377*ea37671dSMatthew Dillon } 378*ea37671dSMatthew Dillon 379*ea37671dSMatthew Dillon /* 380*ea37671dSMatthew Dillon * Look for newline, handle discard mode 381*ea37671dSMatthew Dillon */ 382*ea37671dSMatthew Dillon again: 383*ea37671dSMatthew Dillon for (n = MonitorBufScan; n < MonitorBufEnd; ++n) { 384*ea37671dSMatthew Dillon if (MonitorBuf[n] == '\n') { 385*ea37671dSMatthew Dillon *bufp = MonitorBuf + MonitorBufBeg; 386*ea37671dSMatthew Dillon r = n - MonitorBufBeg; 387*ea37671dSMatthew Dillon MonitorBufBeg = n + 1; 388*ea37671dSMatthew Dillon MonitorBufScan = n + 1; 389*ea37671dSMatthew Dillon 390*ea37671dSMatthew Dillon if (MonitorBufDiscardMode == 0) 391*ea37671dSMatthew Dillon return r; 392*ea37671dSMatthew Dillon MonitorBufDiscardMode = 0; 393*ea37671dSMatthew Dillon goto again; 394*ea37671dSMatthew Dillon } 395*ea37671dSMatthew Dillon } 396*ea37671dSMatthew Dillon 397*ea37671dSMatthew Dillon /* 398*ea37671dSMatthew Dillon * Handle overflow 399*ea37671dSMatthew Dillon */ 400*ea37671dSMatthew Dillon if (n == sizeof(MonitorBuf)) { 401*ea37671dSMatthew Dillon if (MonitorBufBeg) { 402*ea37671dSMatthew Dillon /* 403*ea37671dSMatthew Dillon * Shift the buffer to make room and read more data. 404*ea37671dSMatthew Dillon */ 405*ea37671dSMatthew Dillon bcopy(MonitorBuf + MonitorBufBeg, 406*ea37671dSMatthew Dillon MonitorBuf, 407*ea37671dSMatthew Dillon n - MonitorBufBeg); 408*ea37671dSMatthew Dillon MonitorBufEnd -= MonitorBufBeg; 409*ea37671dSMatthew Dillon MonitorBufScan -= MonitorBufBeg; 410*ea37671dSMatthew Dillon n -= MonitorBufBeg; 411*ea37671dSMatthew Dillon MonitorBufBeg = 0; 412*ea37671dSMatthew Dillon } else if (MonitorBufDiscardMode) { 413*ea37671dSMatthew Dillon /* 414*ea37671dSMatthew Dillon * Overflow. If in discard mode just throw it all 415*ea37671dSMatthew Dillon * away. Stay in discard mode. 416*ea37671dSMatthew Dillon */ 417*ea37671dSMatthew Dillon MonitorBufBeg = 0; 418*ea37671dSMatthew Dillon MonitorBufEnd = 0; 419*ea37671dSMatthew Dillon MonitorBufScan = 0; 420*ea37671dSMatthew Dillon } else { 421*ea37671dSMatthew Dillon /* 422*ea37671dSMatthew Dillon * Overflow. If not in discard mode return a truncated 423*ea37671dSMatthew Dillon * line and enter discard mode. 424*ea37671dSMatthew Dillon * 425*ea37671dSMatthew Dillon * The caller will temporarily set ptr[r] = 0 so make 426*ea37671dSMatthew Dillon * sure that does not overflow our buffer as we are not 427*ea37671dSMatthew Dillon * at a newline. 428*ea37671dSMatthew Dillon * 429*ea37671dSMatthew Dillon * (MonitorBufBeg is 0); 430*ea37671dSMatthew Dillon */ 431*ea37671dSMatthew Dillon *bufp = MonitorBuf + MonitorBufBeg; 432*ea37671dSMatthew Dillon r = n - 1; 433*ea37671dSMatthew Dillon MonitorBufBeg = n; 434*ea37671dSMatthew Dillon MonitorBufScan = n; 435*ea37671dSMatthew Dillon MonitorBufDiscardMode = 1; 436*ea37671dSMatthew Dillon 437*ea37671dSMatthew Dillon return r; 438*ea37671dSMatthew Dillon } 439*ea37671dSMatthew Dillon } 440*ea37671dSMatthew Dillon 441*ea37671dSMatthew Dillon /* 442*ea37671dSMatthew Dillon * Read more data. If there is no data pending then return -1, 443*ea37671dSMatthew Dillon * otherwise loop up to see if more complete line(s) are available. 444*ea37671dSMatthew Dillon */ 445*ea37671dSMatthew Dillon r = pread(fd, 446*ea37671dSMatthew Dillon MonitorBuf + MonitorBufEnd, 447*ea37671dSMatthew Dillon sizeof(MonitorBuf) - MonitorBufEnd, 448*ea37671dSMatthew Dillon MonitorLogOff); 449*ea37671dSMatthew Dillon if (r <= 0) 450*ea37671dSMatthew Dillon return -1; 451*ea37671dSMatthew Dillon MonitorLogOff += r; 452*ea37671dSMatthew Dillon MonitorBufEnd += r; 453*ea37671dSMatthew Dillon goto again; 454*ea37671dSMatthew Dillon } 455*ea37671dSMatthew Dillon 456*ea37671dSMatthew Dillon runstats_t NCursesRunStats = { 457*ea37671dSMatthew Dillon .init = NCursesInit, 458*ea37671dSMatthew Dillon .done = NCursesDone, 459*ea37671dSMatthew Dillon .reset = NCursesReset, 460*ea37671dSMatthew Dillon .update = NCursesUpdate, 461*ea37671dSMatthew Dillon .updateTop = NCursesUpdateTop, 462*ea37671dSMatthew Dillon .updateLogs = NCursesUpdateLogs, 463*ea37671dSMatthew Dillon .sync = NCursesSync 464*ea37671dSMatthew Dillon }; 465