/* Initialises curses */ void initcursestuff(void) { int height, width; if (graph) return; height = width = 0; initscr(); graph = 1; getmaxyx(stdscr, height, width); if (height < 24 || width < 80) xerrx(1, _("You need at least 80 x 24 terminal!")); keypad(stdscr, TRUE); noecho(); cbreak(); start_color(); nodelay(stdscr, FALSE); flushinp(); init_pair(1, COLOR_GREEN, COLOR_BLACK); init_pair(2, COLOR_WHITE, COLOR_BLACK); init_pair(3, COLOR_RED, COLOR_BLACK); init_pair(4, COLOR_MAGENTA, COLOR_BLACK); init_pair(5, COLOR_CYAN, COLOR_BLACK); init_pair(6, COLOR_BLUE, COLOR_BLACK); init_pair(7, COLOR_YELLOW, COLOR_BLACK); }
void _rtld_die(void) { const char *msg = dlerror(); if (msg == NULL) msg = "Fatal error"; xerrx(1, "%s", msg); }
/* Returns a random number between 0 and "range". */ int r(int range) { if (range < 1) xerrx(1, "range of 0 detected!"); #ifdef WIN32 return (int)(rand() % range); #else return (int)(random() % range); #endif /* WIN32 */ }
/* * Note places where rank, score, wpm, cps, and misses have to * be printed, so translators have a much easier job. * * "Rank: %------- Score: %--- WPM: %-- CPS: %---- Misses: %-" */ void initstatus(char *str) { int field; char *p; for (field = 0, p = str; *p != '\0'; p++) { if (*p != '%') continue; switch (field) { case 0: pos.rank = p - str + 23; break; case 1: pos.score = p - str + 23; break; case 2: pos.wpm = p - str + 23; break; case 3: pos.speed = p - str + 23; break; case 4: pos.misses = p - str + 23; break; default: xerrx(1, "1wrong status format"); /* NOTREACHED */ } field++; } if (field != 5) xerrx(1, "2wrong status format"); }
int main(int argc, char **argv) { int lines, row, col = 0; int i, opt; double av[3]; static double max_scale = 0, scale_fact; long tmpdly; static const struct option longopts[] = { {"scale", required_argument, NULL, 's'}, {"delay", required_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; #ifdef HAVE_PROGRAM_INVOCATION_NAME program_invocation_name = program_invocation_short_name; #endif setlocale (LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); while ((opt = getopt_long(argc, argv, "s:d:Vh", longopts, NULL)) != -1) switch (opt) { case 's': max_scale = strtod_or_err(optarg, _("failed to parse argument")); if (max_scale < 0) xerrx(EXIT_FAILURE, _("scale cannot be negative")); break; case 'd': tmpdly = strtol_or_err(optarg, _("failed to parse argument")); if (tmpdly < 1) xerrx(EXIT_FAILURE, _("delay must be positive integer")); else if (UINT_MAX < tmpdly) xerrx(EXIT_FAILURE, _("too large delay value")); dly = tmpdly; break; case 'V': printf(PROCPS_NG_VERSION); return EXIT_SUCCESS; break; case 'h': usage(stdout); default: usage(stderr); } if (argc > optind) if ((fd = open(argv[optind], 1)) == -1) xerr(EXIT_FAILURE, _("can not open tty")); setsize(0); if (max_scale == 0) max_scale = nrows; scale_fact = max_scale; setjmp(jb); col = 0; alrm(0); while (1) { if (scale_fact < max_scale) scale_fact *= 2.0; /* help it drift back up. */ loadavg(&av[0], &av[1], &av[2]); do { lines = av[0] * scale_fact; row = nrows - 1; while (0 <= --lines) { *(screen + row * ncols + col) = '*'; if (--row < 0) { scale_fact /= 2.0; break; } } } while (0 <= lines); while (row >= 0) *(screen + row-- * ncols + col) = ' '; for (i = 1;; ++i) { char *p; row = nrows - (i * scale_fact); if (row < 0) break; if (*(p = screen + row * ncols + col) == ' ') *p = '-'; else *p = '='; } if (++col == ncols) { --col; memmove(screen, screen + 1, scr_size - 1); for (row = nrows - 2; row >= 0; --row) *(screen + row * ncols + col) = ' '; } i = sprintf(screen, " %.2f, %.2f, %.2f", av[0], av[1], av[2]); if (i > 0) screen[i] = ' '; if (write(fd, "\033[H", 3) < 0) xerr(EXIT_FAILURE, _("writing to tty failed")); if (write(fd, screen, scr_size - 1) < 0) xerr(EXIT_FAILURE, _("writing to tty failed")); pause(); } }
/* * Wait for events to and execute a command. Four major concerns are in play: * leading_edge: Global reference to the first file to have changed * reopen_only : Unlink or rename events which require us to spin while * waiting for the file to reappear. These must always be * processed * collate_only: Changes that indicate that more events are likely to occur. * Watch for more events using a short timeout * do_exec : Delay execution until all events have been processed. Allow * the user to edit files while the utility is running without * any visible side-effects * dir_modified: The number of files changed for a directory under watch */ void watch_loop(int kq, char *argv[]) { struct kevent evSet; struct kevent evList[32]; int nev; WatchFile *file; int i; struct timespec evTimeout = { 0, 1000000 }; int reopen_only = 0; int collate_only = 0; int do_exec = 0; int dir_modified = 0; int leading_edge_set = 0; struct stat sb; leading_edge = files[0]; /* default */ if (postpone_opt == 0) run_utility(argv); main: if ((reopen_only == 1) || (collate_only == 1)) nev = xkevent(kq, NULL, 0, evList, 32, &evTimeout); else { nev = xkevent(kq, NULL, 0, evList, 32, NULL); dir_modified = 0; } /* escape for test runner */ if ((nev == -2) && (collate_only == 0)) return; for (i=0; i<nev; i++) { if (evList[i].filter != EVFILT_VNODE) continue; file = (WatchFile *)evList[i].udata; if (file->is_dir == 1) dir_modified += compare_dir_contents(file); else if (leading_edge_set == 0) if ((reopen_only == 0) && (collate_only == 0)) { leading_edge = file; leading_edge_set = 1; } } collate_only = 0; for (i=0; i<nev; i++) { file = (WatchFile *)evList[i].udata; if (evList[i].fflags & NOTE_DELETE || evList[i].fflags & NOTE_RENAME) { EV_SET(&evSet, file->fd, EVFILT_VNODE, EV_DELETE, NOTE_ALL, 0, file); if (xkevent(kq, &evSet, 1, NULL, 0, NULL) == -1) err(1, "failed to remove VNODE event"); if ((file->fd != -1) && (close(file->fd) == -1)) err(1, "unable to close file"); watch_file(kq, file); collate_only = 1; } } if (reopen_only == 1) { reopen_only = 0; goto main; } for (i=0; i<nev && reopen_only == 0; i++) { file = (WatchFile *)evList[i].udata; if ((file->is_dir == 1) && (dir_modified == 0)) continue; if (evList[i].fflags & NOTE_DELETE || evList[i].fflags & NOTE_WRITE || evList[i].fflags & NOTE_RENAME || evList[i].fflags & NOTE_TRUNCATE) { if ((dir_modified > 0) && (restart_opt == 1)) continue; do_exec = 1; } if (evList[i].fflags & NOTE_ATTRIB && S_ISREG(file->mode) != 0 && xstat(file->fn, &sb) == 0 && file->mode != sb.st_mode) { do_exec = 1; file->mode = sb.st_mode; } } if (collate_only == 1) goto main; if (do_exec == 1) { do_exec = 0; run_utility(argv); reopen_only = 1; leading_edge_set = 0; } if (dir_modified > 0) { terminate_utility(); xerrx(2, "directory altered"); } goto main; }
/* * Wait for events to and execute a command or write filename to a FIFO. * Four major concerns are in play here: * leading_edge: Global reference to the first file to have changed * reopen_only : Unlink or rename events which require us to spin while * waiting for the file to reappear. These must always be * processed * collate_only: Changes that indicate that more events are likely to occur. * Watch for more events using a short timeout * do_exec : Delay execution until all events have been processed. Allow * the user to edit files while the utility is running without * any visible side-effects * dir_modified: The number of files changed for a directory under watch */ void watch_loop(int kq, char *argv[]) { struct kevent evSet; struct kevent evList[32]; int nev; WatchFile *file; int i; struct timespec evTimeout = { 0, 1000000 }; int reopen_only = 0; int collate_only = 0; int do_exec = 0; int dir_modified = 0; leading_edge = files[0]; /* default */ if (restart_opt) run_utility(argv); main: if ((reopen_only == 1) || (collate_only == 1)) nev = xkevent(kq, NULL, 0, evList, 32, &evTimeout); else { nev = xkevent(kq, NULL, 0, evList, 32, NULL); dir_modified = 0; } /* escape for test runner */ if ((nev == -2) && (collate_only == 0)) return; for (i=0; i<nev; i++) { #ifdef DEBUG fprintf(stderr, "event %d/%d: ident %d filter %d flags 0x%x " "fflags 0x%x udata %d udata %p\n", i+1, nev, evList[i].ident, evList[i].filter, evList[i].flags, evList[i].fflags, evList[i].data, evList[i].udata); #endif if (evList[i].filter != EVFILT_VNODE) continue; file = (WatchFile *)evList[i].udata; if (file->is_dir == 1) dir_modified += compare_dir_contents(file); if ((i == 0) && (reopen_only == 0) && (collate_only == 0)) leading_edge = file; } collate_only = 0; for (i=0; i<nev; i++) { file = (WatchFile *)evList[i].udata; if (evList[i].fflags & NOTE_DELETE || evList[i].fflags & NOTE_RENAME) { EV_SET(&evSet, file->fd, EVFILT_VNODE, EV_DELETE, NOTE_ALL, 0, file); if (xkevent(kq, &evSet, 1, NULL, 0, NULL) == -1) err(1, "failed to remove VNODE event"); if ((file->fd != -1) && (close(file->fd) == -1)) err(1, "unable to close file"); watch_file(kq, file); collate_only = 1; } } if (reopen_only == 1) { reopen_only = 0; goto main; } for (i=0; i<nev && reopen_only == 0; i++) { file = (WatchFile *)evList[i].udata; if ((file->is_dir == 1) && (dir_modified == 0)) continue; if (evList[i].fflags & NOTE_DELETE || evList[i].fflags & NOTE_WRITE || evList[i].fflags & NOTE_RENAME || evList[i].fflags & NOTE_TRUNCATE) { if (fifo.fd == 0) { if ((dir_modified > 0) && (restart_opt == 1)) continue; do_exec = 1; } else { write(fifo.fd, file->fn, strlen(file->fn)); write(fifo.fd, "\n", 1); fsync(fifo.fd); reopen_only = 1; } } } if (collate_only == 1) goto main; if (do_exec == 1) { do_exec = 0; run_utility(argv); reopen_only = 1; } if (dir_modified > 0) xerrx(2, "directory altered"); goto main; }
int main(int argc, char *argv[]) { int o; unsigned short old_rows; struct slab_info *slab_list = NULL; int run_once = 0, retval = EXIT_SUCCESS; static const struct option longopts[] = { { "delay", required_argument, NULL, 'd' }, { "sort", required_argument, NULL, 's' }, { "once", no_argument, NULL, 'o' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; #ifdef HAVE_PROGRAM_INVOCATION_NAME program_invocation_name = program_invocation_short_name; #endif setlocale (LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); sort_func = DEF_SORT_FUNC; while ((o = getopt_long(argc, argv, "d:s:ohV", longopts, NULL)) != -1) { switch (o) { case 'd': errno = 0; delay = strtol_or_err(optarg, _("illegal delay")); if (delay < 1) xerrx(EXIT_FAILURE, _("delay must be positive integer")); break; case 's': sort_func = (int (*)(const struct slab_info*, const struct slab_info *)) set_sort_func(optarg[0]); break; case 'o': run_once=1; delay = 0; break; case 'V': printf(PROCPS_NG_VERSION); return EXIT_SUCCESS; case 'h': usage(stdout); default: usage(stderr); } } if (tcgetattr(STDIN_FILENO, &saved_tty) == -1) xwarn(_("terminal setting retrieval")); old_rows = rows; term_size(0); if (!run_once) { initscr(); resizeterm(rows, cols); signal(SIGWINCH, term_size); } signal(SIGINT, sigint_handler); do { struct slab_info *curr; struct slab_stat stats; struct timeval tv; fd_set readfds; char c; int i; memset(&stats, 0, sizeof(struct slab_stat)); if (get_slabinfo(&slab_list, &stats)) { retval = EXIT_FAILURE; break; } if (!run_once && old_rows != rows) { resizeterm(rows, cols); old_rows = rows; } move(0, 0); print_line(" %-35s: %d / %d (%.1f%%)\n" " %-35s: %d / %d (%.1f%%)\n" " %-35s: %d / %d (%.1f%%)\n" " %-35s: %.2fK / %.2fK (%.1f%%)\n" " %-35s: %.2fK / %.2fK / %.2fK\n\n", /* Translation Hint: Next five strings must not * exceed 35 length in characters. */ /* xgettext:no-c-format */ _("Active / Total Objects (% used)"), stats.nr_active_objs, stats.nr_objs, 100.0 * stats.nr_active_objs / stats.nr_objs, /* xgettext:no-c-format */ _("Active / Total Slabs (% used)"), stats.nr_active_slabs, stats.nr_slabs, 100.0 * stats.nr_active_slabs / stats.nr_slabs, /* xgettext:no-c-format */ _("Active / Total Caches (% used)"), stats.nr_active_caches, stats.nr_caches, 100.0 * stats.nr_active_caches / stats.nr_caches, /* xgettext:no-c-format */ _("Active / Total Size (% used)"), stats.active_size / 1024.0, stats.total_size / 1024.0, 100.0 * stats.active_size / stats.total_size, _("Minimum / Average / Maximum Object"), stats.min_obj_size / 1024.0, stats.avg_obj_size / 1024.0, stats.max_obj_size / 1024.0); slab_list = slabsort(slab_list); attron(A_REVERSE); /* Translation Hint: Please keep alignment of the * following intact. */ print_line("%-78s\n", _(" OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME")); attroff(A_REVERSE); curr = slab_list; for (i = 0; i < rows - 8 && curr->next; i++) { print_line("%6u %6u %3u%% %7.2fK %6u %8u %9uK %-23s\n", curr->nr_objs, curr->nr_active_objs, curr->use, curr->obj_size / 1024.0, curr->nr_slabs, curr->objs_per_slab, (unsigned)(curr->cache_size / 1024), curr->name); curr = curr->next; } put_slabinfo(slab_list); if (!run_once) { refresh(); FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); tv.tv_sec = delay; tv.tv_usec = 0; if (select(STDOUT_FILENO, &readfds, NULL, NULL, &tv) > 0) { if (read(STDIN_FILENO, &c, 1) != 1) break; parse_input(c); } } } while (delay); tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty); free_slabinfo(slab_list); if (!run_once) endwin(); return retval; }