Справочник по консольным командам Toybox для Android 12


  Ver.0.8.4     Ver.0.8.9     Pending  

Путь: Toys/Other, команды версии: Ver.4     Ver.9


watch

Комментарии в файле watch.c :

usage: watch [-teb] [-n SEC] PROG ARGS

Запускать PROG каждые -n секунд, показывая вывод. Нажмите q, чтобы выйти.
  • -n Период цикла в секундах (по умолчанию 2)
  • -t Не печатать заголовок
  • -e Выход при ошибке
  • -b Звуковой сигнал при ошибке
  • -x команды Прямое выполнение команды (вместо "sh -c")

  • usage: watch [-teb] [-n SEC] PROG ARGS

    Run PROG every -n seconds, showing output. Hit q to quit.
  • -n Loop period in seconds (default 2)
  • -t Don't print header
  • -e Exit on error
  • -b Beep on command error
  • -x Exec command directly (vs "sh -c")

  • Исходный текст в файле watch.c

    #define FOR_watch
    #include "toys.h"
    
    GLOBALS(
      int n;
    
      pid_t pid, oldpid;
    )
    
    // When a child process exits, stop tracking them. Handle errors for -be
    static void watch_child(int sig)
    {
      int status;
      pid_t pid = wait(&status);
    
      status = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127;
      if (status) {
        // TODO should this be beep()?
        if (FLAG(b)) putchar('\b');
        if (FLAG(e)) {
          printf("Exit status %d\r\n", status);
          tty_reset();
          _exit(status);
        }
      }
    
      if (pid == TT.oldpid) TT.oldpid = 0;
      else if (pid == TT.pid) TT.pid = 0;
    }
    
    // Return early for low-ascii characters with special behavior,
    // discard remaining low ascii, escape other unprintable chars normally
    static int watch_escape(FILE *out, int cols, int wc)
    {
      if (wc==27 || (wc>=7 && wc<=13)) return -1;
      if (wc < 32) return 0;
    
      return crunch_escape(out, cols, wc);
    }
    
    void watch_main(void)
    {
      char *cmdv[] = {"/bin/sh", "-c", 0, 0}, *cmd, *ss;
      long long now, then = millitime();
      unsigned width, height, i, cmdlen, len, xx QUIET, yy QUIET, active QUIET;
      struct pollfd pfd[2];
      pid_t pid = 0;
      int fds[2], cc;
    
      // Assemble header line in cmd, cmdlen, and cmdv
      for (i = TT.n%1000, len = i ? 3 : 1; i && !(i%10); i /= 10) len--;
      len = sprintf(toybuf, "Every %u.%0*us:", TT.n/1000, len, i)+1;
      cmdlen = len;
      for (i = 0; toys.optargs[i]; i++) len += strlen(toys.optargs[i])+1;
      ss = stpcpy(cmd = xmalloc(len), toybuf);
      cmdv[2] = cmd+cmdlen;
      for (i = 0; toys.optargs[i]; i++) ss += sprintf(ss, " %s",toys.optargs[i]);
      cmdlen = ss-cmd;
    
      // Need to poll on process output and stdin
      memset(pfd, 0, sizeof(pfd));
      pfd[0].events = pfd[1].events = POLLIN;
    
      xsignal_flags(SIGCHLD, watch_child, SA_RESTART|SA_NOCLDSTOP);
    
      for (;;) {
    
        // Time for a new period?
        if ((now = millitime())>=then) {
    
          // Incrementing then instead of adding offset to now avoids drift,
          // loop is in case we got suspend/resumed and need to skip periods
          while ((then += TT.n)<=now);
          start_redraw(&width, &height);
    
          // redraw the header
          if (!FLAG(t)) {
            time_t t = time(0);
            int pad, ctimelen;
    
            // Get and measure time string, trimming gratuitous \n
            ctimelen = strlen(ss = ctime(&t));
            if (ss[ctimelen-1]=='\n') ss[--ctimelen] = 0;
     
            // print cmdline, then * or ' ' (showing truncation), then ctime 
            pad = width-++ctimelen;
            if (pad>0) draw_trim(cmd, -pad, pad);
            printf("%c", pad<cmdlen ? '*' : ' ');
            if (width) xputs(ss+(width>ctimelen ? 0 : width-1));
            if (yy>=3) xprintf("\r\n");
            xx = 0;
            yy = 2;
          }
    
          // If child didn't exit, send TERM signal to current and KILL to previous
          if (TT.oldpid>0) kill(TT.oldpid, SIGKILL);
          if (TT.pid>0) kill(TT.pid, SIGTERM);
          TT.oldpid = pid;
          if (fds[0]>0) close(fds[0]);
          if (fds[1]>0) close(fds[1]);
    
          // Spawn child process
          fds[0] = fds[1] = -1;
          TT.pid = xpopen_both(FLAG(x) ? toys.optargs : cmdv, fds);
          pfd[1].fd = fds[1];
          active = 1;
        }
    
        // Fetch data from child process or keyboard, with timeout
        len = 0;
        xpoll(pfd, 1+(active && yy<height), then-now);
        if (pfd[0].revents&POLLIN) {
          memset(toybuf, 0, 16);
          cc = scan_key_getsize(toybuf, 0, &width, &height);
          // TODO: ctrl-Z suspend
          // TODO if (cc == -3) redraw();
          if (cc == 3 || tolower(cc) == 'q') xexit();
        }
        if (pfd[0].revents&POLLHUP) xexit();
        if (active) {
          if (pfd[1].revents&POLLIN) len = read(fds[1], toybuf, sizeof(toybuf)-1);
          if (pfd[1].revents&POLLHUP) active = 0;
        }
    
        // Measure output, trim to available display area. Escape low ascii so
        // we don't have to try to parse ansi escapes. TODO: parse ansi escapes.
        if (len<1) continue;
        ss = toybuf;
        toybuf[len] = 0;
        while (yy<height) {
          if (xx==width) {
            xx = 0;
            if (++yy>=height) break;
          }
          xx += crunch_str(&ss, width-xx, stdout, 0, watch_escape);
          if (xx==width) {
            xx = 0;
            if (++yy>=height) break;
            continue;
          }
    
          if (ss-toybuf==len || *ss>27) break;
          cc = *ss++;
          if (cc==27) continue; // TODO
    
          // Handle BEL BS HT LF VT FF CR
          if (cc>=10 && cc<=12) {
            if (++yy>=height) break;
            if (cc=='\n') putchar('\r'), xx = 0;
          }
          putchar(cc);
          if (cc=='\b' && xx) xx--;
          else if (cc=='\t') {
            xx = (xx|7)+1;
            if (xx>width-1) xx = width-1;
          }
        }
      }
    
      if (CFG_TOYBOX_FREE) free(cmd);
    }