busybox/procps/watch.c
<<
>>
Prefs
   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 tarball for details.
   9 */
  10
  11/* BB_AUDIT SUSv3 N/A */
  12/* BB_AUDIT GNU defects -- only option -n is supported. */
  13
  14#include "libbb.h"
  15
  16// procps 2.0.18:
  17// watch [-d] [-n seconds]
  18//   [--differences[=cumulative]] [--interval=seconds] command
  19//
  20// procps-3.2.3:
  21// watch [-dt] [-n seconds]
  22//   [--differences[=cumulative]] [--interval=seconds] [--no-title] command
  23//
  24// (procps 3.x and procps 2.x are forks, not newer/older versions of the same)
  25
  26int watch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  27int watch_main(int argc UNUSED_PARAM, char **argv)
  28{
  29        unsigned opt;
  30        unsigned period = 2;
  31        unsigned width, new_width;
  32        char *header;
  33        char *cmd;
  34
  35        opt_complementary = "-1:n+"; // at least one param; -n NUM
  36        // "+": stop at first non-option (procps 3.x only)
  37        opt = getopt32(argv, "+dtn:", &period);
  38        argv += optind;
  39
  40        // watch from both procps 2.x and 3.x does concatenation. Example:
  41        // watch ls -l "a /tmp" "2>&1" -- ls won't see "a /tmp" as one param
  42        cmd = *argv;
  43        while (*++argv)
  44                cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd
  45
  46        width = (unsigned)-1; // make sure first time new_width != width
  47        header = NULL;
  48        while (1) {
  49                printf("\033[H\033[J");
  50                if (!(opt & 0x2)) { // no -t
  51                        const unsigned time_len = sizeof("1234-67-90 23:56:89");
  52                        time_t t;
  53
  54                        get_terminal_width_height(STDIN_FILENO, &new_width, NULL);
  55                        if (new_width != width) {
  56                                width = new_width;
  57                                free(header);
  58                                header = xasprintf("Every %us: %-*s", period, (int)width, cmd);
  59                        }
  60                        time(&t);
  61                        if (time_len < width)
  62                                strftime(header + width - time_len, time_len,
  63                                        "%Y-%m-%d %H:%M:%S", localtime(&t));
  64
  65                        puts(header);
  66                }
  67                fflush(stdout);
  68                // TODO: 'real' watch pipes cmd's output to itself
  69                // and does not allow it to overflow the screen
  70                // (taking into account linewrap!)
  71                system(cmd);
  72                sleep(period);
  73        }
  74        return 0; // gcc thinks we can reach this :)
  75}
  76