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 Loop period in seconds (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 unsigned opt; 55 unsigned period = 2; 56 unsigned width, new_width; 57 char *header; 58 char *cmd; 59 60#if 0 // maybe ENABLE_DESKTOP? 61 // procps3 compat - "echo TEST | watch cat" doesn't show TEST: 62 close(STDIN_FILENO); 63 xopen("/dev/null", O_RDONLY); 64#endif 65 66 // "+": stop at first non-option (procps 3.x only); -n NUM 67 // at least one param 68 opt = getopt32(argv, "^+" "dtn:+" "\0" "-1", &period); 69 argv += optind; 70 71 // watch from both procps 2.x and 3.x does concatenation. Example: 72 // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param 73 cmd = *argv; 74 while (*++argv) 75 cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd 76 77 width = (unsigned)-1; // make sure first time new_width != width 78 header = NULL; 79 while (1) { 80 /* home; clear to the end of screen */ 81 printf(ESC"[H" ESC"[J"); 82 if (!(opt & 0x2)) { // no -t 83 const unsigned time_len = sizeof("1234-67-90 23:56:89"); 84 85 // STDERR_FILENO is procps3 compat: 86 // "watch ls 2>/dev/null" does not detect tty size 87 new_width = get_terminal_width(STDERR_FILENO); 88 if (new_width != width) { 89 width = new_width; 90 free(header); 91 header = xasprintf("Every %us: %-*s", period, (int)width, cmd); 92 } 93 if (time_len < width) { 94 strftime_YYYYMMDDHHMMSS( 95 header + width - time_len, 96 time_len, 97 /*time_t*:*/ NULL 98 ); 99 } 100 101 // compat: empty line between header and cmd output 102 printf("%s\n\n", header); 103 } 104 fflush_all(); 105 // TODO: 'real' watch pipes cmd's output to itself 106 // and does not allow it to overflow the screen 107 // (taking into account linewrap!) 108 system(cmd); 109 sleep(period); 110 } 111 return 0; // gcc thinks we can reach this :) 112} 113