home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Appls / repeat / repeat.c < prev   
Encoding:
C/C++ Source or Header  |  1990-10-30  |  6.6 KB  |  306 lines  |  [TEXT/????]

  1. /* Repeat a command forever, displaying the output in a window.
  2.    This is useful to have a continuously update from status programs
  3.    like 'ps' or 'lpq'.
  4.    
  5.    Usage: repeat [-d delay] command [arg] ...
  6.    
  7.    To do:
  8.     - adapt textedit width to window width?
  9.     - allocate image buffer dynamically
  10.     - more sensible error handling (allow to cancel)
  11.     - add a menu option to change the delay
  12.     - display the delay somehow
  13.     - use d.ddd seconds notation instead of deciseconds
  14.     - avoid flickering screen in X11 version
  15.       (possibly by using tereplace on the smallest changed section,
  16.       except need a way to turn the caret off???)
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdwin.h>
  22.  
  23. extern char *malloc();
  24.  
  25. WINDOW *win;
  26. TEXTEDIT *tp;
  27.  
  28. #define MAXSIZE 10000
  29.  
  30. #define DELAY 5 /* retry after success in 0.5 seconds */
  31. #define ERRDELAY 50 /* retry after popen error in 5 seconds */
  32.  
  33. int delay = DELAY; /* normal delay */
  34. int errdelay = ERRDELAY; /* delay after popen error */
  35. int tflag = 0; /* Display time above output when set */
  36.  
  37. char *progname = "REPEAT";
  38.  
  39. void usage() {
  40.     wdone();
  41.     fprintf(stderr,
  42.         "usage: %s [-d ddd.d] [-e ddd.d] [-t] cmd [arg] ...\n",
  43.         progname);
  44.     fprintf(stderr, "-d ddd.d: delay N seconds after command\n");
  45.     fprintf(stderr, "-e ddd.d: delay N seconds after error\n");
  46.     fprintf(stderr, "-t      : display current time above output\n");
  47.     exit(2);
  48. }
  49.  
  50. extern int optind;
  51. extern char *optarg;
  52.  
  53. void mainloop();
  54. void rerun();
  55. void drawproc();
  56. char *mktitle();
  57. long getfract();
  58.  
  59. int main(argc, argv)
  60.     int argc;
  61.     char **argv;
  62. {
  63.     int c;
  64.     winitargs(&argc, &argv); /* Must be first for X11 */
  65.     if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0')
  66.         progname = argv[0];
  67.     while ((c = getopt(argc, argv, "d:e:t")) != EOF) {
  68.         switch (c) {
  69.         case 'd':
  70.             delay = getfract(&optarg, 10);
  71.             if (*optarg != '\0') {
  72.                 fprintf(stderr, "-d argument format error\n");
  73.                 usage();
  74.             }
  75.             if (delay <= 0)
  76.                 delay = DELAY;
  77.             break;
  78.         case 'e':
  79.             errdelay = getfract(&optarg, 10);
  80.             if (*optarg != '\0') {
  81.                 fprintf(stderr, "-e argument format error\n");
  82.                 usage();
  83.             }
  84.             if (errdelay <= 0)
  85.                 errdelay = ERRDELAY;
  86.             break;
  87.         case 't':
  88.             tflag = 1;
  89.             break;
  90.         default:
  91.             usage();
  92.             /*NOTREACHED*/
  93.         }
  94.     }
  95.     if (optind >= argc) {
  96.         usage();
  97.         /* NOTREACHED*/
  98.     }
  99.     win = wopen(mktitle(argc-optind, argv+optind), drawproc);
  100.     if (win == NULL) {
  101.         wdone();
  102.         fprintf(stderr, "can't open window\n");
  103.         return 1;
  104.     }
  105.     tp = tecreate(win, 0, 0, 10000, 10000);
  106.     if (tp == NULL) {
  107.         wclose(win);
  108.         wdone();
  109.         fprintf(stderr, "can't create textedit block\n");
  110.         return 1;
  111.     }
  112.     mainloop(argc-optind, argv+optind);
  113.     wdone();
  114.     return 0;
  115. }
  116.  
  117. void mainloop(argc, argv)
  118.     int argc;
  119.     char **argv;
  120. {
  121.     rerun(argc, argv);
  122.     
  123.     for (;;) {
  124.         EVENT e;
  125.         wgetevent(&e);
  126.         switch (e.type) {
  127.         case WE_TIMER:
  128.             rerun(argc, argv);
  129.             break;
  130.         case WE_COMMAND:
  131.             switch (e.u.command) {
  132.             case WC_CLOSE:
  133.             case WC_CANCEL:
  134.                 return;
  135.             case WC_RETURN:
  136.                 rerun(argc, argv);
  137.                 break;
  138.             }
  139.             break;
  140.         case WE_CLOSE:
  141.             return;
  142.         }
  143.     }
  144. }
  145.  
  146. void rerun(argc, argv)
  147.     int argc;
  148.     char **argv;
  149. {
  150.     int fd;
  151.     char *image, *p;
  152.     int left, n;
  153.     
  154.     if ((image = malloc(MAXSIZE)) == NULL) {
  155.         wmessage("can't malloc output buffer");
  156.         wsettimer(win, errdelay);
  157.         return;
  158.     }
  159.     if ((fd = readfrom(argc, argv)) < 0) {
  160.         wmessage("can't start command");
  161.         wsettimer(win, errdelay);
  162.         return;
  163.     }
  164.     left = MAXSIZE;
  165.     p = image;
  166.     if (tflag) {
  167.         extern char *ctime();
  168.         extern long time();
  169.         long t;
  170.         time(&t);
  171.         strcpy(p, ctime(&t));
  172.         p = strchr(p, '\0');
  173.     }
  174.     while (left > 0 && (n = read(fd, p, left)) > 0) {
  175.         p += n;
  176.         left -= n;
  177.     }
  178.     close(fd);
  179.     (void) wait((int *)0); /* Get rid of child -- naively */
  180.     tesetbuf(tp, image, (int)(p - image));
  181.     wsetdocsize(win, 0, tegetbottom(tp));
  182.     wnocaret(win); /* Hack */
  183.     wsettimer(win, delay);
  184. }
  185.  
  186. void drawproc(win, left, top, right, bottom)
  187.     WINDOW *win;
  188. {
  189.     tedrawnew(tp, left, top, right, bottom);
  190. }
  191.  
  192. char *mktitle(argc, argv)
  193.     int argc;
  194.     char **argv;
  195. {
  196.     static char buf[1000];
  197.     int i;
  198.     char *p;
  199.     
  200.     p = buf;
  201.     for (i = 0; i < argc; ++i) {
  202.         if (i > 0) *p++ = ' ';
  203.         strcpy(p, argv[i]);
  204.         p = strchr(p, '\0');
  205.     }
  206.     return buf;
  207. }
  208.  
  209. /* Function to get a number of the form ddd.ddd from a string, without
  210.    using floating point variables.  Input is the address of a string
  211.    pointer, which is incremented by the function to point after the
  212.    last character that was part of the number.
  213.    The function return value is X * scale, where X is the exact value
  214.    read from the string, e.g., for input "3.14" and scale 1000, 3140 is
  215.    returned.
  216.    There is no provision for a leading sign or to leading spaces.
  217.    Overflow goes undetected.
  218. */
  219.  
  220. long getfract(pstr, scale)
  221.     char **pstr;
  222.     long scale;
  223. {
  224.     char *str = *pstr;
  225.     long x = 0;
  226.     int in_fraction = 0;
  227.     char c;
  228.     
  229.     for (; (c = *str) != '\0'; str++) {
  230.         if (c >= '0' && c <= '9') {
  231.             if (in_fraction) {
  232.                 if (scale < 10)
  233.                     break;
  234.                 scale /= 10;
  235.             }
  236.             x = x*10 + (c - '0');
  237.         }
  238.         else if (c == '.' && !in_fraction)
  239.             in_fraction = 1;
  240.         else
  241.             break;
  242.     }
  243.     *pstr = str;
  244.     return x*scale;
  245. }
  246.  
  247. /*
  248.                   Copyright 1989 by Douglas A. Young
  249.  
  250.                            All Rights Reserved
  251.  
  252.    Permission to use, copy, modify, and distribute this software 
  253.    for any purpose and without fee is hereby granted,
  254.    provided that the above copyright notice appear in all copies and that
  255.    both that copyright notice and this permission notice appear in
  256.    supporting documentation. The author disclaims all warranties with 
  257.    regard to this software, including all implied warranties of 
  258.    merchantability and fitness.
  259.  
  260.    Comments and additions may be sent the author at:
  261.  
  262.     dayoung@hplabs.hp.com
  263.  
  264.    Modified to resemble popen(..., "r").  Returns the file descriptor
  265.    from which to read, or negative if an error occurred.  (The pid is lost.)
  266.    Name changed from talkto() to readfrom(). --Guido van Rossum, CWI
  267. */
  268.  
  269. int
  270. readfrom(argc, argv)
  271.     int argc;
  272.     char **argv;
  273. {
  274.     int to_parent[2]; /* pipe descriptors from child->parent */
  275.     int pid;
  276.  
  277.     if (pipe(to_parent) < 0) {
  278.         perror("pipe");
  279.         return -1;
  280.     }
  281.     pid = fork();
  282.     if (pid == 0) {                      /* in the child */
  283.         close(0);                    /* redirect stdin */
  284.         open("/dev/null", 0);
  285.         close(1);                    /* redirect stdout */
  286.         dup(to_parent[1]);
  287.         close(2);                    /* redirect stderr */
  288.         dup(to_parent[1]);
  289.  
  290.         close(to_parent[0]);
  291.         close(to_parent[1]);
  292.  
  293.         execvp(argv[0], argv);       /* exec the new cmd */
  294.         perror(argv[0]);             /* error in child! */
  295.         _exit(127);
  296.     }
  297.     else if (pid > 0) {                  /* in the parent */
  298.         close(to_parent[1]);
  299.         return to_parent[0];
  300.     }
  301.     else {                               /* error! */
  302.         perror("vfork");
  303.         return -1;
  304.     }
  305. }
  306.