* Includes termios.h in sys/ioctl.h, for TIOCGWINSZ.
* added watch command, which executes a program periodically, showing output full screen. * added watch to the image. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30900 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -60,7 +60,7 @@ SYSTEM_BIN = "[" addattr alert arp base64 basename bash bc beep bootman bzip2
|
||||
tr traceroute translate trash true truncate tsort tty
|
||||
uname unchop unexpand unmount uniq unlink unrar unshar unzip unzipsfx
|
||||
<bin>updatedb uptime urlwrapper useradd uudecode uuencode
|
||||
vdir version vim vmstat waitfor wc wget whoami xargs xres yes
|
||||
vdir version vim vmstat waitfor watch wc wget whoami xargs xres yes
|
||||
zdiff zforce zgrep zip zipcloak <bin>zipgrep zipnote zipsplit zmore znew
|
||||
;
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef _SYS_IOCTL_H
|
||||
#define _SYS_IOCTL_H
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
/* These only work on sockets for now */
|
||||
#define FIONBIO 0xbe000000
|
||||
#define FIONREAD 0xbe000001
|
||||
|
||||
@@ -5,6 +5,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
UsePrivateHeaders app shared storage support usb ;
|
||||
UsePrivateSystemHeaders ;
|
||||
SubDirHdrs $(HAIKU_TOP) src add-ons kernel file_cache ;
|
||||
UseLibraryHeaders ncurses ;
|
||||
|
||||
local haiku-utils_rsrc = [ FGristFiles haiku-utils.rsrc ] ;
|
||||
|
||||
@@ -170,6 +171,11 @@ StdBinCommands
|
||||
filepanel.cpp
|
||||
: be tracker : $(haiku-utils_rsrc) ;
|
||||
|
||||
# standard commands that need libncurses.a
|
||||
StdBinCommands
|
||||
watch.c
|
||||
: libncurses.a : $(haiku-utils_rsrc) ;
|
||||
|
||||
SubInclude HAIKU_TOP src bin addattr ;
|
||||
SubInclude HAIKU_TOP src bin bash ;
|
||||
SubInclude HAIKU_TOP src bin bc ;
|
||||
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
/* watch -- execute a program repeatedly, displaying output fullscreen
|
||||
*
|
||||
* Based on the original 1991 'watch' by Tony Rems <[email protected]>
|
||||
* (with mods and corrections by Francois Pinard).
|
||||
*
|
||||
* Substantially reworked, new features (differences option, SIGWINCH
|
||||
* handling, unlimited command length, long line handling) added Apr 1999 by
|
||||
* Mike Coleman <[email protected]>.
|
||||
*
|
||||
* Changes by Albert Cahalan, 2002-2003.
|
||||
*/
|
||||
|
||||
#define VERSION "0.2.0"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <ncurses.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
/* #include "proc/procps.h" */
|
||||
|
||||
static struct option longopts[] = {
|
||||
{"differences", optional_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"interval", required_argument, 0, 'n'},
|
||||
{"no-title", no_argument, 0, 't'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static char usage[] =
|
||||
"Usage: %s [-dhntv] [--differences[=cumulative]] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
|
||||
|
||||
static char *progname;
|
||||
|
||||
static int curses_started = 0;
|
||||
static int height = 24, width = 80;
|
||||
static int screen_size_changed = 0;
|
||||
static int first_screen = 1;
|
||||
static int show_title = 2; // number of lines used, 2 or 0
|
||||
|
||||
#define min(x,y) ((x) > (y) ? (y) : (x))
|
||||
|
||||
//static void do_usage(void) NORETURN;
|
||||
static void do_usage(void)
|
||||
{
|
||||
fprintf(stderr, usage, progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//static void do_exit(int status) NORETURN;
|
||||
static void do_exit(int status)
|
||||
{
|
||||
if (curses_started)
|
||||
endwin();
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/* signal handler */
|
||||
//static void die(int notused) NORETURN;
|
||||
static void die(int notused)
|
||||
{
|
||||
(void) notused;
|
||||
do_exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
winch_handler(int notused)
|
||||
{
|
||||
(void) notused;
|
||||
screen_size_changed = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
get_terminal_size(void)
|
||||
{
|
||||
struct winsize w;
|
||||
if (ioctl(2, TIOCGWINSZ, &w) == 0) {
|
||||
if (w.ws_row > 0)
|
||||
height = w.ws_row;
|
||||
if (w.ws_col > 0)
|
||||
width = w.ws_col;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int optc;
|
||||
int option_differences = 0,
|
||||
option_differences_cumulative = 0,
|
||||
option_help = 0, option_version = 0;
|
||||
int interval = 2;
|
||||
char *command;
|
||||
int command_length = 0; /* not including final \0 */
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
progname = argv[0];
|
||||
|
||||
while ((optc = getopt_long(argc, argv, "+d::hn:vt", longopts, (int *) 0))
|
||||
!= EOF) {
|
||||
switch (optc) {
|
||||
case 'd':
|
||||
option_differences = 1;
|
||||
if (optarg)
|
||||
option_differences_cumulative = 1;
|
||||
break;
|
||||
case 'h':
|
||||
option_help = 1;
|
||||
break;
|
||||
case 't':
|
||||
show_title = 0;
|
||||
break;
|
||||
case 'n':
|
||||
{
|
||||
char *str;
|
||||
interval = strtol(optarg, &str, 10);
|
||||
if (!*optarg || *str)
|
||||
do_usage();
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
option_version = 1;
|
||||
break;
|
||||
default:
|
||||
do_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (option_version) {
|
||||
fprintf(stderr, "%s\n", VERSION);
|
||||
if (!option_help)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (option_help) {
|
||||
fprintf(stderr, usage, progname);
|
||||
fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr);
|
||||
fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr);
|
||||
fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr);
|
||||
fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr);
|
||||
fputs(" -v, --version\t\t\t\tprint the version number\n", stderr);
|
||||
fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
do_usage();
|
||||
|
||||
command = strdup(argv[optind++]);
|
||||
command_length = strlen(command);
|
||||
for (; optind < argc; optind++) {
|
||||
char *endp;
|
||||
int s = strlen(argv[optind]);
|
||||
command = realloc(command, command_length + s + 2); /* space and \0 */
|
||||
endp = command + command_length;
|
||||
*endp = ' ';
|
||||
memcpy(endp + 1, argv[optind], s);
|
||||
command_length += 1 + s; /* space then string length */
|
||||
command[command_length] = '\0';
|
||||
}
|
||||
|
||||
get_terminal_size();
|
||||
|
||||
/* Catch keyboard interrupts so we can put tty back in a sane state. */
|
||||
signal(SIGINT, die);
|
||||
signal(SIGTERM, die);
|
||||
signal(SIGHUP, die);
|
||||
signal(SIGWINCH, winch_handler);
|
||||
|
||||
/* Set up tty for curses use. */
|
||||
curses_started = 1;
|
||||
initscr();
|
||||
nonl();
|
||||
noecho();
|
||||
cbreak();
|
||||
|
||||
for (;;) {
|
||||
time_t t = time(NULL);
|
||||
char *ts = ctime(&t);
|
||||
int tsl = strlen(ts);
|
||||
char *header;
|
||||
FILE *p;
|
||||
int x, y;
|
||||
int oldeolseen = 1;
|
||||
|
||||
if (screen_size_changed) {
|
||||
get_terminal_size();
|
||||
resizeterm(height, width);
|
||||
clear();
|
||||
/* redrawwin(stdscr); */
|
||||
screen_size_changed = 0;
|
||||
first_screen = 1;
|
||||
}
|
||||
|
||||
if (show_title) {
|
||||
// left justify interval and command,
|
||||
// right justify time, clipping all to fit window width
|
||||
asprintf(&header, "Every %ds: %.*s",
|
||||
interval, min(width - 1, command_length), command);
|
||||
mvaddstr(0, 0, header);
|
||||
if (strlen(header) > (size_t) (width - tsl - 1))
|
||||
mvaddstr(0, width - tsl - 4, "... ");
|
||||
mvaddstr(0, width - tsl + 1, ts);
|
||||
free(header);
|
||||
}
|
||||
|
||||
if (!(p = popen(command, "r"))) {
|
||||
perror("popen");
|
||||
do_exit(2);
|
||||
}
|
||||
|
||||
for (y = show_title; y < height; y++) {
|
||||
int eolseen = 0, tabpending = 0;
|
||||
for (x = 0; x < width; x++) {
|
||||
int c = ' ';
|
||||
int attr = 0;
|
||||
|
||||
if (!eolseen) {
|
||||
/* if there is a tab pending, just spit spaces until the
|
||||
next stop instead of reading characters */
|
||||
if (!tabpending)
|
||||
do
|
||||
c = getc(p);
|
||||
while (c != EOF && !isprint(c)
|
||||
&& c != '\n'
|
||||
&& c != '\t');
|
||||
if (c == '\n')
|
||||
if (!oldeolseen && x == 0) {
|
||||
x = -1;
|
||||
continue;
|
||||
} else
|
||||
eolseen = 1;
|
||||
else if (c == '\t')
|
||||
tabpending = 1;
|
||||
if (c == EOF || c == '\n' || c == '\t')
|
||||
c = ' ';
|
||||
if (tabpending && (((x + 1) % 8) == 0))
|
||||
tabpending = 0;
|
||||
}
|
||||
move(y, x);
|
||||
if (option_differences) {
|
||||
int oldch = inch();
|
||||
char oldc = oldch & A_CHARTEXT;
|
||||
attr = !first_screen
|
||||
&& (c != oldc
|
||||
||
|
||||
(option_differences_cumulative
|
||||
&& (oldch & A_ATTRIBUTES)));
|
||||
}
|
||||
if (attr)
|
||||
standout();
|
||||
addch(c);
|
||||
if (attr)
|
||||
standend();
|
||||
}
|
||||
oldeolseen = eolseen;
|
||||
}
|
||||
|
||||
pclose(p);
|
||||
|
||||
first_screen = 0;
|
||||
refresh();
|
||||
sleep(interval);
|
||||
}
|
||||
|
||||
endwin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user