watch: new usage & fix coding style
Coding style fixed and more readable help output. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
parent
2865ded64e
commit
6dd092412f
663
watch.c
663
watch.c
@ -1,11 +1,12 @@
|
|||||||
/* watch -- execute a program repeatedly, displaying output fullscreen
|
/*
|
||||||
|
* watch -- execute a program repeatedly, displaying output fullscreen
|
||||||
*
|
*
|
||||||
* Based on the original 1991 'watch' by Tony Rems <rembo@unisoft.com>
|
* Based on the original 1991 'watch' by Tony Rems <rembo@unisoft.com>
|
||||||
* (with mods and corrections by Francois Pinard).
|
* (with mods and corrections by Francois Pinard).
|
||||||
*
|
*
|
||||||
* Substantially reworked, new features (differences option, SIGWINCH
|
* Substantially reworked, new features (differences option, SIGWINCH
|
||||||
* handling, unlimited command length, long line handling) added Apr 1999 by
|
* handling, unlimited command length, long line handling) added Apr
|
||||||
* Mike Coleman <mkc@acm.org>.
|
* 1999 by Mike Coleman <mkc@acm.org>.
|
||||||
*
|
*
|
||||||
* Changes by Albert Cahalan, 2002-2003.
|
* Changes by Albert Cahalan, 2002-2003.
|
||||||
* stderr handling, exec, and beep option added by Morty Abzug, 2008
|
* stderr handling, exec, and beep option added by Morty Abzug, 2008
|
||||||
@ -13,137 +14,132 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "proc/procps.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <termios.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#include "proc/procps.h"
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <ncursesw/ncurses.h>
|
#include <ncursesw/ncurses.h>
|
||||||
#else
|
#else
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
|
|
||||||
#ifdef FORCE_8BIT
|
#ifdef FORCE_8BIT
|
||||||
#undef isprint
|
#undef isprint
|
||||||
#define isprint(x) ( (x>=' '&&x<='~') || (x>=0xa0) )
|
#define isprint(x) ( (x>=' '&&x<='~') || (x>=0xa0) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct option longopts[] = {
|
|
||||||
{"color", no_argument, 0, 'c' },
|
|
||||||
{"differences", optional_argument, 0, 'd'},
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{"interval", required_argument, 0, 'n'},
|
|
||||||
{"beep", no_argument, 0, 'b'},
|
|
||||||
{"errexit", no_argument, 0, 'e'},
|
|
||||||
{"exec", no_argument, 0, 'x'},
|
|
||||||
{"precise", no_argument, 0, 'p'},
|
|
||||||
{"no-title", no_argument, 0, 't'},
|
|
||||||
{"version", no_argument, 0, 'v'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static char usage[] =
|
|
||||||
"Usage: %s [-bdhnptvx] [--beep] [--color] [--differences[=cumulative]] [--exec] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
|
|
||||||
|
|
||||||
static char *progname;
|
|
||||||
|
|
||||||
static int curses_started = 0;
|
static int curses_started = 0;
|
||||||
static int height = 24, width = 80;
|
static int height = 24, width = 80;
|
||||||
static int screen_size_changed = 0;
|
static int screen_size_changed = 0;
|
||||||
static int first_screen = 1;
|
static int first_screen = 1;
|
||||||
static int show_title = 2; // number of lines used, 2 or 0
|
static int show_title = 2; /* number of lines used, 2 or 0 */
|
||||||
static int precise_timekeeping = 0;
|
static int precise_timekeeping = 0;
|
||||||
|
|
||||||
#define min(x,y) ((x) > (y) ? (y) : (x))
|
#define min(x,y) ((x) > (y) ? (y) : (x))
|
||||||
#define MAX_ANSIBUF 10
|
#define MAX_ANSIBUF 10
|
||||||
|
|
||||||
|
static void __attribute__ ((__noreturn__))
|
||||||
|
usage(FILE * out)
|
||||||
|
{
|
||||||
|
fprintf(out,
|
||||||
|
"\nUsage: %s [options] command\n"
|
||||||
|
"\nOptions:\n", program_invocation_short_name);
|
||||||
|
fprintf(out,
|
||||||
|
" -b, --beep beep if command has a non-zero exit\n"
|
||||||
|
" -c, --color interpret ANSI color sequences\n"
|
||||||
|
" -e, --errexit exit if command has a non-zero exit\n"
|
||||||
|
" -f, --differences highlight changes between updates\n"
|
||||||
|
" -n, --interval <secs> seconds to wait between updates\n"
|
||||||
|
" -p, --precise attempt run command in precise intervals\n"
|
||||||
|
" -t, --no-title turn off header\n"
|
||||||
|
" -x, --exec pass command to exec instead of \"sh -c\"\n"
|
||||||
|
" -h, --help display this help text\n"
|
||||||
|
" -v, --version display version information and exit\n");
|
||||||
|
fprintf(out, "\nFor more information see watch(1).\n");
|
||||||
|
|
||||||
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
static void init_ansi_colors(void)
|
static void init_ansi_colors(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
short ncurses_colors[] = {
|
short ncurses_colors[] = {
|
||||||
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
|
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
|
||||||
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
|
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
|
||||||
|
};
|
||||||
|
|
||||||
for (i=0; i< 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
init_pair(i+1, ncurses_colors[i], -1);
|
init_pair(i + 1, ncurses_colors[i], -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_ansi_attribute(const int attrib)
|
static void set_ansi_attribute(const int attrib)
|
||||||
{
|
{
|
||||||
switch (attrib)
|
switch (attrib) {
|
||||||
{
|
case -1:
|
||||||
case -1:
|
return;
|
||||||
return;
|
case 0:
|
||||||
case 0:
|
standend();
|
||||||
standend();
|
return;
|
||||||
return;
|
case 1:
|
||||||
case 1:
|
attrset(A_BOLD);
|
||||||
attrset(A_BOLD);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
if (attrib >= 30 && attrib <= 37) {
|
||||||
if (attrib >= 30 && attrib <= 37) {
|
color_set(attrib - 29, NULL);
|
||||||
color_set(attrib-29,NULL);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_ansi(FILE *fp)
|
static void process_ansi(FILE * fp)
|
||||||
{
|
{
|
||||||
int i,c, num1, num2;
|
int i, c, num1, num2;
|
||||||
char buf[MAX_ANSIBUF];
|
char buf[MAX_ANSIBUF];
|
||||||
char *nextnum;
|
char *nextnum;
|
||||||
|
|
||||||
|
c = getc(fp);
|
||||||
c= getc(fp);
|
if (c != '[') {
|
||||||
if (c != '[') {
|
ungetc(c, fp);
|
||||||
ungetc(c, fp);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
for (i = 0; i < MAX_ANSIBUF; i++) {
|
||||||
for(i=0; i<MAX_ANSIBUF; i++)
|
c = getc(fp);
|
||||||
{
|
/* COLOUR SEQUENCE ENDS in 'm' */
|
||||||
c = getc(fp);
|
if (c == 'm') {
|
||||||
if (c == 'm') //COLOUR SEQUENCE ENDS in 'm'
|
buf[i] = '\0';
|
||||||
{
|
break;
|
||||||
buf[i] = '\0';
|
}
|
||||||
break;
|
if (c < '0' && c > '9' && c != ';') {
|
||||||
}
|
while (--i >= 0)
|
||||||
if (c < '0' && c > '9' && c != ';')
|
ungetc(buf[i], fp);
|
||||||
{
|
return;
|
||||||
while(--i >= 0)
|
}
|
||||||
ungetc(buf[i],fp);
|
buf[i] = (char)c;
|
||||||
return;
|
}
|
||||||
}
|
num1 = strtol(buf, &nextnum, 10);
|
||||||
buf[i] = (char)c;
|
if (nextnum != buf && nextnum[0] != '\0')
|
||||||
}
|
num2 = strtol(nextnum + 1, NULL, 10);
|
||||||
num1 = strtol(buf, &nextnum, 10);
|
else
|
||||||
if (nextnum != buf && nextnum[0] != '\0')
|
num2 = -1;
|
||||||
num2 = strtol(nextnum+1, NULL, 10);
|
set_ansi_attribute(num1);
|
||||||
else
|
set_ansi_attribute(num2);
|
||||||
num2 = -1;
|
|
||||||
set_ansi_attribute(num1);
|
|
||||||
set_ansi_attribute(num2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_usage(void) NORETURN;
|
static void __attribute__ ((__noreturn__)) do_exit(int status)
|
||||||
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)
|
if (curses_started)
|
||||||
endwin();
|
endwin();
|
||||||
@ -151,17 +147,13 @@ static void do_exit(int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* signal handler */
|
/* signal handler */
|
||||||
static void die(int notused) NORETURN;
|
static void die(int notused __attribute__ ((__unused__)))
|
||||||
static void die(int notused)
|
|
||||||
{
|
{
|
||||||
(void) notused;
|
do_exit(EXIT_SUCCESS);
|
||||||
do_exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void winch_handler(int notused __attribute__ ((__unused__)))
|
||||||
winch_handler(int notused)
|
|
||||||
{
|
{
|
||||||
(void) notused;
|
|
||||||
screen_size_changed = 1;
|
screen_size_changed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,46 +162,53 @@ static char env_row_buf[24];
|
|||||||
static int incoming_cols;
|
static int incoming_cols;
|
||||||
static int incoming_rows;
|
static int incoming_rows;
|
||||||
|
|
||||||
static void
|
static void get_terminal_size(void)
|
||||||
get_terminal_size(void)
|
|
||||||
{
|
{
|
||||||
struct winsize w;
|
struct winsize w;
|
||||||
if(!incoming_cols){ // have we checked COLUMNS?
|
if (!incoming_cols) {
|
||||||
|
/* have we checked COLUMNS? */
|
||||||
const char *s = getenv("COLUMNS");
|
const char *s = getenv("COLUMNS");
|
||||||
incoming_cols = -1;
|
incoming_cols = -1;
|
||||||
if(s && *s){
|
if (s && *s) {
|
||||||
long t;
|
long t;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
t = strtol(s, &endptr, 0);
|
t = strtol(s, &endptr, 0);
|
||||||
if(!*endptr && (t>0) && (t<(long)666)) incoming_cols = (int)t;
|
if (!*endptr && (t > 0) && (t < (long)666))
|
||||||
|
incoming_cols = (int)t;
|
||||||
width = incoming_cols;
|
width = incoming_cols;
|
||||||
snprintf(env_col_buf, sizeof env_col_buf, "COLUMNS=%d", width);
|
snprintf(env_col_buf, sizeof env_col_buf, "COLUMNS=%d",
|
||||||
|
width);
|
||||||
putenv(env_col_buf);
|
putenv(env_col_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!incoming_rows){ // have we checked LINES?
|
if (!incoming_rows) {
|
||||||
|
/* have we checked LINES? */
|
||||||
const char *s = getenv("LINES");
|
const char *s = getenv("LINES");
|
||||||
incoming_rows = -1;
|
incoming_rows = -1;
|
||||||
if(s && *s){
|
if (s && *s) {
|
||||||
long t;
|
long t;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
t = strtol(s, &endptr, 0);
|
t = strtol(s, &endptr, 0);
|
||||||
if(!*endptr && (t>0) && (t<(long)666)) incoming_rows = (int)t;
|
if (!*endptr && (t > 0) && (t < (long)666))
|
||||||
|
incoming_rows = (int)t;
|
||||||
height = incoming_rows;
|
height = incoming_rows;
|
||||||
snprintf(env_row_buf, sizeof env_row_buf, "LINES=%d", height);
|
snprintf(env_row_buf, sizeof env_row_buf, "LINES=%d",
|
||||||
|
height);
|
||||||
putenv(env_row_buf);
|
putenv(env_row_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (incoming_cols<0 || incoming_rows<0){
|
if (incoming_cols < 0 || incoming_rows < 0) {
|
||||||
if (ioctl(2, TIOCGWINSZ, &w) == 0) {
|
if (ioctl(2, TIOCGWINSZ, &w) == 0) {
|
||||||
if (incoming_rows<0 && w.ws_row > 0){
|
if (incoming_rows < 0 && w.ws_row > 0) {
|
||||||
height = w.ws_row;
|
height = w.ws_row;
|
||||||
snprintf(env_row_buf, sizeof env_row_buf, "LINES=%d", height);
|
snprintf(env_row_buf, sizeof env_row_buf,
|
||||||
|
"LINES=%d", height);
|
||||||
putenv(env_row_buf);
|
putenv(env_row_buf);
|
||||||
}
|
}
|
||||||
if (incoming_cols<0 && w.ws_col > 0){
|
if (incoming_cols < 0 && w.ws_col > 0) {
|
||||||
width = w.ws_col;
|
width = w.ws_col;
|
||||||
snprintf(env_col_buf, sizeof env_col_buf, "COLUMNS=%d", width);
|
snprintf(env_col_buf, sizeof env_col_buf,
|
||||||
|
"COLUMNS=%d", width);
|
||||||
putenv(env_col_buf);
|
putenv(env_col_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,180 +218,186 @@ get_terminal_size(void)
|
|||||||
/* get current time in usec */
|
/* get current time in usec */
|
||||||
typedef unsigned long long watch_usec_t;
|
typedef unsigned long long watch_usec_t;
|
||||||
#define USECS_PER_SEC (1000000ull)
|
#define USECS_PER_SEC (1000000ull)
|
||||||
watch_usec_t get_time_usec() {
|
watch_usec_t get_time_usec()
|
||||||
|
{
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
return USECS_PER_SEC*now.tv_sec + now.tv_usec;
|
return USECS_PER_SEC * now.tv_sec + now.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
// read a wide character from a popen'd stream
|
/* read a wide character from a popen'd stream */
|
||||||
#define MAX_ENC_BYTES 16
|
#define MAX_ENC_BYTES 16
|
||||||
wint_t my_getwc(FILE *s);
|
wint_t my_getwc(FILE * s);
|
||||||
wint_t my_getwc(FILE *s) {
|
wint_t my_getwc(FILE * s)
|
||||||
char i[MAX_ENC_BYTES]; //assuming no encoding ever consumes more than 16 bytes
|
{
|
||||||
|
/* assuming no encoding ever consumes more than 16 bytes */
|
||||||
|
char i[MAX_ENC_BYTES];
|
||||||
int byte = 0;
|
int byte = 0;
|
||||||
int convert;
|
int convert;
|
||||||
int x;
|
int x;
|
||||||
wchar_t rval;
|
wchar_t rval;
|
||||||
while(1) {
|
while (1) {
|
||||||
i[byte] = getc(s);
|
i[byte] = getc(s);
|
||||||
if (i[byte]==EOF) { return WEOF; }
|
if (i[byte] == EOF) {
|
||||||
|
return WEOF;
|
||||||
|
}
|
||||||
byte++;
|
byte++;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
mbtowc(NULL, NULL, 0);
|
mbtowc(NULL, NULL, 0);
|
||||||
convert = mbtowc(&rval, i, byte);
|
convert = mbtowc(&rval, i, byte);
|
||||||
x = errno;
|
x = errno;
|
||||||
if(convert > 0) { return rval; } //legal conversion
|
if (convert > 0) {
|
||||||
if(byte == MAX_ENC_BYTES) {
|
/* legal conversion */
|
||||||
while(byte > 1) { ungetc(i[--byte], s); } //at least *try* to fix up
|
return rval;
|
||||||
errno = -EILSEQ;
|
}
|
||||||
return WEOF;
|
if (byte == MAX_ENC_BYTES) {
|
||||||
|
while (byte > 1) {
|
||||||
|
/* at least *try* to fix up */
|
||||||
|
ungetc(i[--byte], s);
|
||||||
|
}
|
||||||
|
errno = -EILSEQ;
|
||||||
|
return WEOF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
|
|
||||||
int
|
int main(int argc, char *argv[])
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
{
|
||||||
int optc;
|
int optc;
|
||||||
int option_differences = 0,
|
int option_differences = 0,
|
||||||
option_differences_cumulative = 0,
|
option_differences_cumulative = 0,
|
||||||
option_exec = 0,
|
option_exec = 0,
|
||||||
option_beep = 0,
|
option_beep = 0,
|
||||||
option_color = 0,
|
option_color = 0,
|
||||||
option_errexit = 0,
|
option_errexit = 0, option_help = 0, option_version = 0;
|
||||||
option_help = 0, option_version = 0;
|
|
||||||
double interval = 2;
|
double interval = 2;
|
||||||
char *command;
|
char *command;
|
||||||
char **command_argv;
|
char **command_argv;
|
||||||
int command_length = 0; /* not including final \0 */
|
int command_length = 0; /* not including final \0 */
|
||||||
watch_usec_t next_loop; /* next loop time in us, used for precise time
|
watch_usec_t next_loop; /* next loop time in us, used for precise time
|
||||||
keeping only */
|
* keeping only */
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
wchar_t *wcommand = NULL;
|
wchar_t *wcommand = NULL;
|
||||||
int wcommand_columns = 0; /* not including final \0 */
|
int wcommand_columns = 0; /* not including final \0 */
|
||||||
int wcommand_characters = 0; /* not including final \0 */
|
int wcommand_characters = 0; /* not including final \0 */
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
|
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
int status;
|
int status;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
static struct option longopts[] = {
|
||||||
progname = argv[0];
|
{"color", no_argument, 0, 'c'},
|
||||||
|
{"differences", optional_argument, 0, 'd'},
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"interval", required_argument, 0, 'n'},
|
||||||
|
{"beep", no_argument, 0, 'b'},
|
||||||
|
{"errexit", no_argument, 0, 'e'},
|
||||||
|
{"exec", no_argument, 0, 'x'},
|
||||||
|
{"precise", no_argument, 0, 'p'},
|
||||||
|
{"no-title", no_argument, 0, 't'},
|
||||||
|
{"version", no_argument, 0, 'v'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
while ((optc = getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *) 0))
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
while ((optc =
|
||||||
|
getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *)0))
|
||||||
!= EOF) {
|
!= EOF) {
|
||||||
switch (optc) {
|
switch (optc) {
|
||||||
case 'b':
|
case 'b':
|
||||||
option_beep = 1;
|
option_beep = 1;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
option_color = 1;
|
option_color = 1;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
option_differences = 1;
|
option_differences = 1;
|
||||||
if (optarg)
|
if (optarg)
|
||||||
option_differences_cumulative = 1;
|
option_differences_cumulative = 1;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
option_errexit = 1;
|
option_errexit = 1;
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
option_help = 1;
|
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
show_title = 0;
|
show_title = 0;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
option_exec = 1;
|
option_exec = 1;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
interval = strtod(optarg, &str);
|
interval = strtod(optarg, &str);
|
||||||
if (!*optarg || *str)
|
if (!*optarg || *str)
|
||||||
do_usage();
|
usage(stderr);
|
||||||
if(interval < 0.1)
|
if (interval < 0.1)
|
||||||
interval = 0.1;
|
interval = 0.1;
|
||||||
if(interval > ~0u/1000000)
|
if (interval > ~0u / 1000000)
|
||||||
interval = ~0u/1000000;
|
interval = ~0u / 1000000;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
precise_timekeeping = 1;
|
precise_timekeeping = 1;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'h':
|
||||||
option_version = 1;
|
usage(stdout);
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
display_version();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
default:
|
default:
|
||||||
do_usage();
|
usage(stderr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option_version) {
|
|
||||||
fprintf(stderr, "%s\n", PACKAGE_NAME " version " PACKAGE_VERSION);
|
|
||||||
if (!option_help)
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option_help) {
|
|
||||||
fprintf(stderr, usage, progname);
|
|
||||||
fputs(" -b, --beep\t\t\t\tbeep if the command has a non-zero exit\n", stderr);
|
|
||||||
fputs(" -d, --differences[=cumulative]\thighlight changes between updates\n", stderr);
|
|
||||||
fputs("\t\t(cumulative means highlighting is cumulative)\n", stderr);
|
|
||||||
fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\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(" -p, --precise\t\t\t\tprecise timing, ignore command run time\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);
|
|
||||||
fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind >= argc)
|
if (optind >= argc)
|
||||||
do_usage();
|
usage(stderr);
|
||||||
|
|
||||||
command_argv=&(argv[optind]); /* save for later */
|
/* save for later */
|
||||||
|
command_argv = &(argv[optind]);
|
||||||
|
|
||||||
command = strdup(argv[optind++]);
|
command = strdup(argv[optind++]);
|
||||||
command_length = strlen(command);
|
command_length = strlen(command);
|
||||||
for (; optind < argc; optind++) {
|
for (; optind < argc; optind++) {
|
||||||
char *endp;
|
char *endp;
|
||||||
int s = strlen(argv[optind]);
|
int s = strlen(argv[optind]);
|
||||||
command = realloc(command, command_length + s + 2); /* space and \0 */
|
/* space and \0 */
|
||||||
|
command = realloc(command, command_length + s + 2);
|
||||||
endp = command + command_length;
|
endp = command + command_length;
|
||||||
*endp = ' ';
|
*endp = ' ';
|
||||||
memcpy(endp + 1, argv[optind], s);
|
memcpy(endp + 1, argv[optind], s);
|
||||||
command_length += 1 + s; /* space then string length */
|
/* space then string length */
|
||||||
|
command_length += 1 + s;
|
||||||
command[command_length] = '\0';
|
command[command_length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
// convert to wide for printing purposes
|
/* convert to wide for printing purposes */
|
||||||
//mbstowcs(NULL, NULL, 0);
|
/*mbstowcs(NULL, NULL, 0); */
|
||||||
wcommand_characters = mbstowcs(NULL, command, 0);
|
wcommand_characters = mbstowcs(NULL, command, 0);
|
||||||
if(wcommand_characters < 0) {
|
if (wcommand_characters < 0) {
|
||||||
fprintf(stderr, "Unicode Handling Error\n");
|
fprintf(stderr, "Unicode Handling Error\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
wcommand = (wchar_t*)malloc((wcommand_characters+1) * sizeof(wcommand));
|
wcommand =
|
||||||
if(wcommand == NULL) {
|
(wchar_t *) malloc((wcommand_characters + 1) * sizeof(wcommand));
|
||||||
|
if (wcommand == NULL) {
|
||||||
fprintf(stderr, "Unicode Handling Error (malloc)\n");
|
fprintf(stderr, "Unicode Handling Error (malloc)\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
mbstowcs(wcommand, command, wcommand_characters+1);
|
mbstowcs(wcommand, command, wcommand_characters + 1);
|
||||||
wcommand_columns = wcswidth(wcommand, -1);
|
wcommand_columns = wcswidth(wcommand, -1);
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
|
|
||||||
|
|
||||||
get_terminal_size();
|
get_terminal_size();
|
||||||
|
|
||||||
/* Catch keyboard interrupts so we can put tty back in a sane state. */
|
/* Catch keyboard interrupts so we can put tty back in a sane
|
||||||
|
* state. */
|
||||||
signal(SIGINT, die);
|
signal(SIGINT, die);
|
||||||
signal(SIGTERM, die);
|
signal(SIGTERM, die);
|
||||||
signal(SIGHUP, die);
|
signal(SIGHUP, die);
|
||||||
@ -401,14 +406,14 @@ main(int argc, char *argv[])
|
|||||||
/* Set up tty for curses use. */
|
/* Set up tty for curses use. */
|
||||||
curses_started = 1;
|
curses_started = 1;
|
||||||
initscr();
|
initscr();
|
||||||
if (option_color) {
|
if (option_color) {
|
||||||
if (has_colors()) {
|
if (has_colors()) {
|
||||||
start_color();
|
start_color();
|
||||||
use_default_colors();
|
use_default_colors();
|
||||||
init_ansi_colors();
|
init_ansi_colors();
|
||||||
} else
|
} else
|
||||||
option_color = 0;
|
option_color = 0;
|
||||||
}
|
}
|
||||||
nonl();
|
nonl();
|
||||||
noecho();
|
noecho();
|
||||||
cbreak();
|
cbreak();
|
||||||
@ -435,44 +440,70 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (show_title) {
|
if (show_title) {
|
||||||
// left justify interval and command,
|
/*
|
||||||
// right justify time, clipping all to fit window width
|
* left justify interval and command, right
|
||||||
|
* justify time, clipping all to fit window
|
||||||
|
* width
|
||||||
|
*/
|
||||||
int hlen = asprintf(&header, "Every %.1fs: ", interval);
|
int hlen = asprintf(&header, "Every %.1fs: ", interval);
|
||||||
|
|
||||||
// the rules:
|
/*
|
||||||
// width < tsl : print nothing
|
* the rules:
|
||||||
// width < tsl + hlen + 1: print ts
|
* width < tsl : print nothing
|
||||||
// width = tsl + hlen + 1: print header, ts
|
* width < tsl + hlen + 1: print ts
|
||||||
// width < tsl + hlen + 4: print header, ..., ts
|
* width = tsl + hlen + 1: print header, ts
|
||||||
// width < tsl + hlen + wcommand_columns: print header, truncated wcommand, ..., ts
|
* width < tsl + hlen + 4: print header, ..., ts
|
||||||
// width > "": print header, wcomand, ts
|
* width < tsl + hlen + wcommand_columns: print
|
||||||
// this is slightly different from how it used to be
|
* header, truncated wcommand,
|
||||||
if(width >= tsl) {
|
* ..., ts
|
||||||
if(width >= tsl + hlen + 1) {
|
* width > "": print header, wcomand, ts
|
||||||
|
* this is slightly different from how it used to be
|
||||||
|
*/
|
||||||
|
if (width >= tsl) {
|
||||||
|
if (width >= tsl + hlen + 1) {
|
||||||
mvaddstr(0, 0, header);
|
mvaddstr(0, 0, header);
|
||||||
if(width >= tsl + hlen + 2) {
|
if (width >= tsl + hlen + 2) {
|
||||||
if(width < tsl + hlen + 4) {
|
if (width < tsl + hlen + 4) {
|
||||||
mvaddstr(0, width - tsl - 4, "... ");
|
mvaddstr(0,
|
||||||
}else{
|
width - tsl -
|
||||||
|
4, "... ");
|
||||||
|
} else {
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
if(width < tsl + hlen + wcommand_columns) {
|
if (width <
|
||||||
// print truncated
|
tsl + hlen +
|
||||||
|
wcommand_columns) {
|
||||||
|
/* print truncated */
|
||||||
int avail_columns = width - tsl - hlen;
|
int avail_columns = width - tsl - hlen;
|
||||||
int using_columns = wcommand_columns;
|
int using_columns = wcommand_columns;
|
||||||
int using_characters = wcommand_characters;
|
int using_characters = wcommand_characters;
|
||||||
while(using_columns > avail_columns - 4) {
|
while (using_columns > avail_columns - 4) {
|
||||||
using_characters--;
|
using_characters--;
|
||||||
using_columns = wcswidth(wcommand, using_characters);
|
using_columns
|
||||||
|
=
|
||||||
|
wcswidth
|
||||||
|
(wcommand,
|
||||||
|
using_characters);
|
||||||
}
|
}
|
||||||
mvaddnwstr(0, hlen, wcommand, using_characters);
|
mvaddnwstr(0,
|
||||||
mvaddstr(0, width - tsl - 4, "... ");
|
hlen,
|
||||||
}else{
|
wcommand,
|
||||||
mvaddwstr(0, hlen, wcommand);
|
using_characters);
|
||||||
|
mvaddstr(0,
|
||||||
|
width -
|
||||||
|
tsl -
|
||||||
|
4,
|
||||||
|
"... ");
|
||||||
|
} else {
|
||||||
|
mvaddwstr(0,
|
||||||
|
hlen,
|
||||||
|
wcommand);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
mvaddnstr(0, hlen, command, width - tsl - hlen);
|
mvaddnstr(0, hlen,
|
||||||
#endif /* WITH_WATCH8BIT */
|
command,
|
||||||
|
width - tsl -
|
||||||
|
hlen);
|
||||||
|
#endif /* WITH_WATCH8BIT */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,101 +514,99 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* allocate pipes */
|
/* allocate pipes */
|
||||||
if (pipe(pipefd)<0) {
|
if (pipe(pipefd) < 0)
|
||||||
perror("pipe");
|
err(7, "pipe");
|
||||||
do_exit(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* flush stdout and stderr, since we're about to do fd stuff */
|
/* flush stdout and stderr, since we're about to do fd stuff */
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
/* fork to prepare to run command */
|
/* fork to prepare to run command */
|
||||||
child=fork();
|
child = fork();
|
||||||
|
|
||||||
if (child<0) { /* fork error */
|
if (child < 0) { /* fork error */
|
||||||
perror("fork");
|
err(2, "fork");
|
||||||
do_exit(2);
|
} else if (child == 0) { /* in child */
|
||||||
} else if (child==0) { /* in child */
|
close(pipefd[0]); /* child doesn't need read side of pipe */
|
||||||
close (pipefd[0]); /* child doesn't need read side of pipe */
|
close(1); /* prepare to replace stdout with pipe */
|
||||||
close (1); /* prepare to replace stdout with pipe */
|
if (dup2(pipefd[1], 1) < 0) { /* replace stdout with write side of pipe */
|
||||||
if (dup2 (pipefd[1], 1)<0) { /* replace stdout with write side of pipe */
|
err(3, "dup2");
|
||||||
perror("dup2");
|
|
||||||
exit(3);
|
|
||||||
}
|
}
|
||||||
dup2(1, 2); /* stderr should default to stdout */
|
dup2(1, 2); /* stderr should default to stdout */
|
||||||
|
|
||||||
if (option_exec) { /* pass command to exec instead of system */
|
if (option_exec) { /* pass command to exec instead of system */
|
||||||
if (execvp(command_argv[0], command_argv)==-1) {
|
if (execvp(command_argv[0], command_argv) == -1) {
|
||||||
perror("exec");
|
err(4, "exec");
|
||||||
exit(4);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status=system(command); /* watch manpage promises sh quoting */
|
status = system(command); /* watch manpage promises sh quoting */
|
||||||
|
|
||||||
/* propagate command exit status as child exit status */
|
/* propagate command exit status as child exit status */
|
||||||
if (!WIFEXITED(status)) { /* child exits nonzero if command does */
|
if (!WIFEXITED(status)) { /* child exits nonzero if command does */
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
exit(WEXITSTATUS(status));
|
exit(WEXITSTATUS(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise, we're in parent */
|
/* otherwise, we're in parent */
|
||||||
close(pipefd[1]); /* close write side of pipe */
|
close(pipefd[1]); /* close write side of pipe */
|
||||||
if ((p=fdopen(pipefd[0], "r"))==NULL) {
|
if ((p = fdopen(pipefd[0], "r")) == NULL)
|
||||||
perror("fdopen");
|
err(5, "fdopen");
|
||||||
do_exit(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (y = show_title; y < height; y++) {
|
for (y = show_title; y < height; y++) {
|
||||||
int eolseen = 0, tabpending = 0;
|
int eolseen = 0, tabpending = 0;
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
wint_t carry = WEOF;
|
wint_t carry = WEOF;
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
for (x = 0; x < width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
wint_t c = ' ';
|
wint_t c = ' ';
|
||||||
#else
|
#else
|
||||||
int c = ' ';
|
int c = ' ';
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
int attr = 0;
|
int attr = 0;
|
||||||
|
|
||||||
if (!eolseen) {
|
if (!eolseen) {
|
||||||
/* if there is a tab pending, just spit spaces until the
|
/* if there is a tab pending, just
|
||||||
next stop instead of reading characters */
|
* spit spaces until the next stop
|
||||||
if (!tabpending)
|
* instead of reading characters */
|
||||||
|
if (!tabpending)
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
do {
|
do {
|
||||||
if(carry == WEOF) {
|
if (carry == WEOF) {
|
||||||
c = my_getwc(p);
|
c = my_getwc(p);
|
||||||
}else{
|
} else {
|
||||||
c = carry;
|
c = carry;
|
||||||
carry = WEOF;
|
carry = WEOF;
|
||||||
}
|
}
|
||||||
}while (c != WEOF && !isprint(c) && c<12
|
} while (c != WEOF
|
||||||
&& wcwidth(c) == 0
|
&& !isprint(c)
|
||||||
&& c != L'\n'
|
&& c < 12
|
||||||
&& c != L'\t'
|
&& wcwidth(c) == 0
|
||||||
&& (c != L'\033' || option_color != 1));
|
&& c != L'\n'
|
||||||
|
&& c != L'\t'
|
||||||
|
&& (c != L'\033'
|
||||||
|
|| option_color !=
|
||||||
|
1));
|
||||||
#else
|
#else
|
||||||
do
|
do
|
||||||
c = getc(p);
|
c = getc(p);
|
||||||
while (c != EOF && !isprint(c)
|
while (c != EOF && !isprint(c)
|
||||||
&& c != '\n'
|
&& c != '\n'
|
||||||
&& c != '\t'
|
&& c != '\t'
|
||||||
&& (c != L'\033' || option_color != 1));
|
&& (c != L'\033'
|
||||||
#endif /* WITH_WATCH8BIT */
|
|| option_color !=
|
||||||
if (c == L'\033' && option_color == 1) {
|
1));
|
||||||
x--;
|
#endif /* WITH_WATCH8BIT */
|
||||||
process_ansi(p);
|
if (c == L'\033' && option_color == 1) {
|
||||||
continue;
|
x--;
|
||||||
}
|
process_ansi(p);
|
||||||
if (c == L'\n')
|
continue;
|
||||||
|
}
|
||||||
|
if (c == L'\n')
|
||||||
if (!oldeolseen && x == 0) {
|
if (!oldeolseen && x == 0) {
|
||||||
x = -1;
|
x = -1;
|
||||||
continue;
|
continue;
|
||||||
@ -586,31 +615,33 @@ main(int argc, char *argv[])
|
|||||||
else if (c == L'\t')
|
else if (c == L'\t')
|
||||||
tabpending = 1;
|
tabpending = 1;
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
if (x==width-1 && wcwidth(c)==2) {
|
if (x == width - 1 && wcwidth(c) == 2) {
|
||||||
y++;
|
y++;
|
||||||
x = -1; //process this double-width
|
x = -1; /* process this double-width */
|
||||||
carry = c; //character on the next line
|
carry = c; /* character on the next line */
|
||||||
continue; //because it won't fit here
|
continue; /* because it won't fit here */
|
||||||
}
|
}
|
||||||
if (c == WEOF || c == L'\n' || c == L'\t')
|
if (c == WEOF || c == L'\n'
|
||||||
c = L' ';
|
|| c == L'\t')
|
||||||
|
c = L' ';
|
||||||
#else
|
#else
|
||||||
if (c == EOF || c == '\n' || c == '\t')
|
if (c == EOF || c == '\n' || c == '\t')
|
||||||
c = ' ';
|
c = ' ';
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
if (tabpending && (((x + 1) % 8) == 0))
|
if (tabpending && (((x + 1) % 8) == 0))
|
||||||
tabpending = 0;
|
tabpending = 0;
|
||||||
}
|
}
|
||||||
move(y, x);
|
move(y, x);
|
||||||
if (option_differences) {
|
if (option_differences) {
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
cchar_t oldc;
|
cchar_t oldc;
|
||||||
in_wch(&oldc);
|
in_wch(&oldc);
|
||||||
attr = !first_screen
|
attr = !first_screen
|
||||||
&& ((wchar_t)c != oldc.chars[0]
|
&& ((wchar_t) c != oldc.chars[0]
|
||||||
||
|
||
|
||||||
(option_differences_cumulative
|
(option_differences_cumulative
|
||||||
&& (oldc.attr & A_ATTRIBUTES)));
|
&& (oldc.
|
||||||
|
attr & A_ATTRIBUTES)));
|
||||||
#else
|
#else
|
||||||
chtype oldch = inch();
|
chtype oldch = inch();
|
||||||
unsigned char oldc = oldch & A_CHARTEXT;
|
unsigned char oldc = oldch & A_CHARTEXT;
|
||||||
@ -619,21 +650,25 @@ main(int argc, char *argv[])
|
|||||||
||
|
||
|
||||||
(option_differences_cumulative
|
(option_differences_cumulative
|
||||||
&& (oldch & A_ATTRIBUTES)));
|
&& (oldch & A_ATTRIBUTES)));
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
}
|
}
|
||||||
if (attr)
|
if (attr)
|
||||||
standout();
|
standout();
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
addnwstr((wchar_t*)&c,1);
|
addnwstr((wchar_t *) & c, 1);
|
||||||
#else
|
#else
|
||||||
addch(c);
|
addch(c);
|
||||||
#endif /* WITH_WATCH8BIT */
|
#endif /* WITH_WATCH8BIT */
|
||||||
if (attr)
|
if (attr)
|
||||||
standend();
|
standend();
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
if(wcwidth(c) == 0) { x--; }
|
if (wcwidth(c) == 0) {
|
||||||
if(wcwidth(c) == 2) { x++; }
|
x--;
|
||||||
#endif /* WITH_WATCH8BIT */
|
}
|
||||||
|
if (wcwidth(c) == 2) {
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
#endif /* WITH_WATCH8BIT */
|
||||||
}
|
}
|
||||||
oldeolseen = eolseen;
|
oldeolseen = eolseen;
|
||||||
}
|
}
|
||||||
@ -641,29 +676,29 @@ main(int argc, char *argv[])
|
|||||||
fclose(p);
|
fclose(p);
|
||||||
|
|
||||||
/* harvest child process and get status, propagated from command */
|
/* harvest child process and get status, propagated from command */
|
||||||
if (waitpid(child, &status, 0)<0) {
|
if (waitpid(child, &status, 0) < 0)
|
||||||
perror("waitpid");
|
err(8, "waitpid");
|
||||||
do_exit(8);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* if child process exited in error, beep if option_beep is set */
|
/* if child process exited in error, beep if option_beep is set */
|
||||||
if ((!WIFEXITED(status) || WEXITSTATUS(status))) {
|
if ((!WIFEXITED(status) || WEXITSTATUS(status))) {
|
||||||
if (option_beep) beep();
|
if (option_beep)
|
||||||
if (option_errexit) do_exit(8);
|
beep();
|
||||||
|
if (option_errexit)
|
||||||
|
exit(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
first_screen = 0;
|
first_screen = 0;
|
||||||
refresh();
|
refresh();
|
||||||
if (precise_timekeeping) {
|
if (precise_timekeeping) {
|
||||||
watch_usec_t cur_time = get_time_usec();
|
watch_usec_t cur_time = get_time_usec();
|
||||||
next_loop += USECS_PER_SEC*interval;
|
next_loop += USECS_PER_SEC * interval;
|
||||||
if (cur_time < next_loop)
|
if (cur_time < next_loop)
|
||||||
usleep(next_loop - cur_time);
|
usleep(next_loop - cur_time);
|
||||||
} else
|
} else
|
||||||
usleep(interval * 1000000);
|
usleep(interval * 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
endwin();
|
endwin();
|
||||||
|
|
||||||
return 0;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user