1/* vi: set sw=4 ts=4: */ 2/* 3 * Mini watch implementation for busybox 4 * 5 * Copyright (C) 2001 by Michael Habermann <mhabermann@gmx.de> 6 * Copyrigjt (C) Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) 7 * 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 */ 10//config:config WATCH 11//config: bool "watch (4.4 kb)" 12//config: default y 13//config: help 14//config: watch is used to execute a program periodically, showing 15//config: output to the screen. 16 17//applet:IF_WATCH(APPLET(watch, BB_DIR_BIN, BB_SUID_DROP)) 18 19//kbuild:lib-$(CONFIG_WATCH) += watch.o 20 21//usage:#define watch_trivial_usage 22//usage: "[-n SEC] [-t] PROG ARGS" 23//usage:#define watch_full_usage "\n\n" 24//usage: "Run PROG periodically\n" 25//usage: "\n -n SEC Period (default 2)" 26//usage: "\n -t Don't print header" 27//usage: 28//usage:#define watch_example_usage 29//usage: "$ watch date\n" 30//usage: "Mon Dec 17 10:31:40 GMT 2000\n" 31//usage: "Mon Dec 17 10:31:42 GMT 2000\n" 32//usage: "Mon Dec 17 10:31:44 GMT 2000" 33 34/* BB_AUDIT SUSv3 N/A */ 35/* BB_AUDIT GNU defects -- only option -n is supported. */ 36 37#include "libbb.h" 38 39#define ESC "\033" 40 41// procps 2.0.18: 42// watch [-d] [-n seconds] 43// [--differences[=cumulative]] [--interval=seconds] command 44// 45// procps-3.2.3: 46// watch [-dt] [-n seconds] 47// [--differences[=cumulative]] [--interval=seconds] [--no-title] command 48// 49// (procps 3.x and procps 2.x are forks, not newer/older versions of the same) 50 51int watch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 52int watch_main(int argc UNUSED_PARAM, char **argv) 53{ 54 duration_t period; 55 char *period_str = (char*) "2"; 56 unsigned opt; 57 unsigned width, new_width; 58 char *header; 59 char *cmd; 60 61#if 0 // maybe ENABLE_DESKTOP? 62 // procps3 compat - "echo TEST | watch cat" doesn't show TEST: 63 close(STDIN_FILENO); 64 xopen("/dev/null", O_RDONLY); 65#endif 66 67 // "+": stop at first non-option (procps 3.x only); -n NUM 68 // at least one param 69 opt = getopt32(argv, "^+" "dtn:" "\0" "-1", &period_str); 70 argv += optind; 71 72 // watch from both procps 2.x and 3.x does concatenation. Example: 73 // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param 74 cmd = *argv; 75 while (*++argv) 76 cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd 77 78 period = parse_duration_str(period_str); 79 width = (unsigned)-1; // make sure first time new_width != width 80 header = NULL; 81 while (1) { 82 /* home; clear to the end of screen */ 83 printf(ESC"[H" ESC"[J"); 84 if (!(opt & 0x2)) { // no -t 85 const unsigned time_len = sizeof("1234-67-90 23:56:89"); 86 87 // STDERR_FILENO is procps3 compat: 88 // "watch ls 2>/dev/null" does not detect tty size 89 new_width = get_terminal_width(STDERR_FILENO); 90 if (new_width != width) { 91 width = new_width; 92 free(header); 93 header = xasprintf("Every" 94 " %"IF_FLOAT_DURATION(".1")DURATION_FMT"s:" 95 " %-*s", 96 period, 97 (int)width, cmd 98 ); 99 } 100 if (time_len < width) { 101 strftime_YYYYMMDDHHMMSS( 102 header + width - time_len, 103 time_len, 104 /*time_t*:*/ NULL 105 ); 106 } 107 108 // compat: empty line between header and cmd output 109 printf("%s\n\n", header); 110 } 111 fflush_all(); 112 // TODO: 'real' watch pipes cmd's output to itself 113 // and does not allow it to overflow the screen 114 // (taking into account linewrap!) 115 system(cmd); 116 sleep_for_duration(period); 117 } 118 return 0; // gcc thinks we can reach this :) 119} 120