home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / sun / volume1 / contool2.2 / part03 / contool.c next >
Encoding:
C/C++ Source or Header  |  1989-10-26  |  18.2 KB  |  634 lines

  1. /************************************************************************/
  2. /*    Copyright 1988, 1989 by Chuck Musciano and Harris Corporation    */
  3. /*                                    */
  4. /*    Permission to use, copy, modify, and distribute this software    */
  5. /*    and its documentation for any purpose and without fee is    */
  6. /*    hereby granted, provided that the above copyright notice    */
  7. /*    appear in all copies and that both that copyright notice and    */
  8. /*    this permission notice appear in supporting documentation, and    */
  9. /*    that the name of Chuck Musciano and Harris Corporation not be    */
  10. /*    used in advertising or publicity pertaining to distribution    */
  11. /*    of the software without specific, written prior permission.    */
  12. /*    Chuck Musciano and Harris Corporation make no representations    */
  13. /*    about the suitability of this software for any purpose.  It is    */
  14. /*    provided "as is" without express or implied warranty.  This     */
  15. /*    software may not be sold without the prior explicit permission    */
  16. /*    of Harris Corporation.                        */
  17. /************************************************************************/
  18.  
  19. #include    <stdio.h>
  20. #include    <fcntl.h>
  21. #include    <sys/ioctl.h>
  22. #include    <sys/file.h>
  23. #include    <sys/types.h>
  24. #include    <sys/stat.h>
  25.  
  26. #include    <suntool/sunview.h>
  27. #include    <suntool/textsw.h>
  28. #include    <suntool/icon_load.h>
  29.  
  30. #include    "contool.h"
  31.  
  32. EXPORT    char    filter_path[256];        /* -c */
  33. EXPORT    int    blink_icon = TRUE;        /* -i */
  34. EXPORT    int    pop_open = FALSE;        /* -p */
  35. EXPORT    int    beep_amount = BEEP_COUNT;    /* -s */
  36. EXPORT    int    do_time_stamp = TRUE;
  37. EXPORT    f_ptr    filters = NULL;
  38. EXPORT    f_ptr    curr_filter = NULL;
  39.  
  40. PUBLIC    Frame    confirmer;
  41.  
  42. PRIVATE    char    *ct_usage = "usage: contool [-b <file>] [-c <file>] [-d <size>] [-f <file>] [-g <file>] [-l <size>] [-n] [-o <logfile>] [-p] [-r <amt>] [-s <amt>]\n";
  43.  
  44. PRIVATE    Frame    bf;
  45. PRIVATE    Frame    dialog = NULL;
  46. PRIVATE    Textsw    text;
  47. PRIVATE    Icon    good, bad, inverse;
  48. PRIVATE    struct    pixrect    *good_pr, *bad_pr, *inv_pr;
  49. PRIVATE    Menu_item    stop_blink;
  50. PRIVATE    Rect    open_rect;
  51.  
  52. PRIVATE    char    bad_icon[512];            /* -b */
  53. PRIVATE    int    delete_amt = TEXT_DELETE_SIZE;    /* -d */
  54. PRIVATE    char    inv_icon[512];            /* -f */
  55. PRIVATE    char    good_icon[512];            /* -g */
  56. PRIVATE    int    size_limit = TEXT_SIZE_LIMIT;    /* -l */
  57. PRIVATE    int    resolution = TS_INTERVAL;    /* -r */
  58.  
  59. PRIVATE    int    bad_is_up;
  60. PRIVATE    int    beep_count;
  61. PRIVATE    int    blinking = FALSE;
  62. PRIVATE    int    event_in_progress = FALSE;
  63. PRIVATE    int    explicit_filters = FALSE;
  64. PRIVATE    int    icon_height;
  65. PRIVATE    int    icon_width;
  66. PRIVATE    FILE    *master = NULL;
  67. PRIVATE    int    old_time = 0;
  68. PRIVATE    char    *program;
  69. PRIVATE    FILE    *slave = NULL;
  70. PRIVATE    FILE    *logfile = NULL;
  71.  
  72. PRIVATE    struct    itimerval    timer = {{0, 500000}, {0, 500000}};
  73.  
  74. /************************************************************************/
  75. /*    First, some basic console utility routines             */
  76. /************************************************************************/
  77.  
  78. /************************************************************************/
  79. PRIVATE    acquire_console(path)
  80.  
  81. char    *path;
  82.  
  83. {
  84.     if (ioctl(fileno(slave), TIOCCONS, NULL) == -1) {
  85.        fprintf(stderr, "%s: could not attach %s to /dev/console\n", program, path);
  86.        exit(1);
  87.        }
  88. }
  89.  
  90. /************************************************************************/
  91. PRIVATE    clear_messages()
  92.  
  93. {
  94.     textsw_reset(text, 0, 0);
  95.     old_time = 0;
  96. }
  97.  
  98. /************************************************************************/
  99. PRIVATE    stop_blinking()
  100.  
  101. {
  102.     notify_set_itimer_func(bf, NULL, ITIMER_REAL, NULL, NULL);
  103.     window_set(bf, FRAME_ICON, good, 0);
  104.     blinking = FALSE;
  105.     menu_set(stop_blink, MENU_INACTIVE, TRUE, 0);
  106. }
  107.  
  108. /************************************************************************/
  109. PRIVATE    edit_filters()
  110.  
  111. {    Frame    create_dialog_box();
  112.  
  113.     if (dialog == NULL)
  114.        dialog = create_dialog_box(bf);
  115.     update_edit_dialog(filters);
  116.     update_defaults();
  117.     window_set(dialog, WIN_SHOW, TRUE, 0);
  118. }
  119.  
  120. /************************************************************************/
  121. /*    Now, filter and regular expression handlers            */
  122. /************************************************************************/
  123.  
  124. /************************************************************************/
  125. PRIVATE    internal_message(a, b, c, d, e, f)
  126.  
  127. int    a, b, c, d, e, f;
  128.  
  129. {    char    buf[512];
  130.  
  131.     sprintf(buf, a, b, c, d, e, f);
  132.     time_stamp();
  133.     write_log(buf);
  134.     do_insertion(buf, strlen(buf));
  135. }
  136.  
  137. /************************************************************************/
  138. PRIVATE    internal_error(a, b, c, d, e, f)
  139.  
  140. int    a, b, c, d, e, f;
  141.  
  142. {    char    buf[512];
  143.  
  144.     sprintf(buf, a, b, c, d, e, f);
  145.     time_stamp();
  146.     fprintf(stderr, "*** %s: %s\n", program, buf);
  147. }
  148.  
  149. /************************************************************************/
  150. PRIVATE    load_filters()
  151.  
  152. {    char    *result;
  153.     struct    stat    sb;
  154.     f_ptr    new_filters, f;
  155.     static    int    load_time = 0;
  156.  
  157.     if (access(filter_path, R_OK) == -1) {
  158.        if (explicit_filters && load_time == 0) {
  159.           internal_error("filter file %s cannot be accessed", filter_path);
  160.           load_time = 1;
  161.           }
  162.        return;
  163.        }
  164.     if (stat(filter_path, &sb) == 0 && sb.st_mtime > load_time)
  165.        if (new_filters = read_filters(filter_path, internal_error)) {
  166.           for (f = new_filters; f->start; f++)
  167.              if (result = compile_exp(f, f->start, f->end)) {
  168.                 internal_error(result);
  169.                 f->valid = FALSE;
  170.                 }
  171.           free_filters(filters);
  172.           filters = new_filters;
  173.           internal_message("*** filters loaded from %s\n", filter_path);
  174.           load_time = sb.st_mtime;
  175.           }
  176. }
  177.  
  178. /************************************************************************/
  179. /*    Various event handlers for the console frame            */
  180. /************************************************************************/
  181.  
  182. /************************************************************************/
  183. PRIVATE    Notify_value    blink_proc(me, which)
  184.  
  185. int    *me;
  186. int    which;
  187.  
  188. {
  189.     if (event_in_progress)
  190.        return(NOTIFY_DONE);
  191.     if (beep_count > 0) {
  192.        window_bell(bf);
  193.        beep_count--;
  194.        }
  195.     if (blinking) {
  196.        if (bad_is_up)
  197.           window_set(bf, FRAME_ICON, inverse, 0);
  198.        else
  199.           window_set(bf, FRAME_ICON, bad, 0);
  200.        bad_is_up = !bad_is_up;
  201.        }
  202.     if (beep_count == 0 && !blinking)
  203.        notify_set_itimer_func(bf, blink_proc, ITIMER_REAL, NULL, NULL);
  204.     return(NOTIFY_DONE);
  205. }
  206.  
  207. /************************************************************************/
  208. PRIVATE    Notify_value    close_proc(frame, event, arg, type)
  209.  
  210. Frame    frame;
  211. Event    *event;
  212. Notify_arg    arg;
  213. Notify_event_type    type;
  214.  
  215. {    int    init_closed, curr_closed, is_resize;
  216.     Notify_value    value;
  217.     Rect    *temp;
  218.  
  219.     event_in_progress = TRUE;
  220.     init_closed = (int) window_get(frame, FRAME_CLOSED);
  221.     is_resize = (event_id(event) == WIN_RESIZE);
  222.     value = notify_next_event_func(frame, event, arg, type);
  223.     curr_closed = (int) window_get(frame, FRAME_CLOSED);
  224.     if (init_closed != curr_closed)
  225.        if (!curr_closed && blinking) {
  226.           notify_set_itimer_func(bf, blink_proc, ITIMER_REAL, NULL, NULL);
  227.           window_set(bf, FRAME_ICON, good, 0);
  228.           blinking = FALSE;
  229.           menu_set(stop_blink, MENU_INACTIVE, TRUE, 0);
  230.           }
  231.     event_in_progress = FALSE;
  232.     if (is_resize) {
  233.        temp = (Rect *) window_get(frame, FRAME_OPEN_RECT);
  234.        if (temp->r_width <= icon_width && temp->r_height <= icon_height) { /* override spurious resize request */
  235.           window_set(frame, FRAME_OPEN_RECT, &open_rect, FRAME_CLOSED, FALSE, 0);
  236.           notify_set_itimer_func(bf, blink_proc, ITIMER_REAL, NULL, NULL);
  237.           window_set(bf, FRAME_ICON, good, 0);
  238.           blinking = FALSE;
  239.           menu_set(stop_blink, MENU_INACTIVE, TRUE, 0);
  240.           }
  241.        else /* save away new open rect */
  242.           open_rect = *temp;
  243.        }
  244.     return(value);
  245. }
  246.  
  247. /************************************************************************/
  248. PRIVATE    Notify_value    destroy_proc(frame, status)
  249.  
  250. Frame    frame;
  251. Destroy_status    status;
  252.  
  253. {
  254.     if (status == DESTROY_CHECKING) {
  255.        if (dialog)
  256.           window_destroy(dialog);
  257.        if (confirmer)
  258.           window_destroy(confirmer);
  259.        textsw_reset(text, 0, 0);
  260.        return(NOTIFY_DONE);
  261.        }
  262.     else
  263.        return(notify_next_destroy_func(frame, status));
  264. }
  265.  
  266. /************************************************************************/
  267. /*    Routines which handle capturing and displaying messages        */
  268. /************************************************************************/
  269.  
  270. /************************************************************************/
  271. PRIVATE    write_log(s)
  272.  
  273. char    *s;
  274.  
  275. {    int    t;
  276.     static    char    hostname[100] = "";
  277.  
  278.     if (logfile) {
  279.        if (*hostname == NULL) 
  280.           if (gethostname(hostname, 99) != 0)
  281.              strcpy(hostname, "(unknown)");
  282.        t = time(0);
  283.        fseek(logfile, 0L, 2);
  284.        fprintf(logfile, "%s\t%.16s\t%s", hostname, ctime(&t) + 4, s);
  285.        fflush(logfile);
  286.        }
  287. }
  288.  
  289. /************************************************************************/
  290. PRIVATE    do_insertion(buf, len)
  291.  
  292. char    *buf;
  293. int    len;
  294.  
  295. {    int    first, last;
  296.  
  297.     while (len > size_limit - ((int) window_get(text, TEXTSW_LENGTH) - TEXT_SIZE_FUZZ)) { /* make some room */
  298.        first = 1;
  299.        last = TEXTSW_INFINITY;
  300.        if (textsw_find_bytes(text, &first, &last, "\n<<<", 4, 0) == -1)
  301.           if (textsw_find_bytes(text, &first, &last, "\n", 1, 0) == -1)
  302.              first = delete_amt;
  303.        textsw_delete(text, 0, first + 1);
  304.        }
  305.     window_set(text, TEXTSW_INSERTION_POINT, TEXTSW_INFINITY, 0);
  306.     textsw_insert(text, buf, len);
  307. }
  308.  
  309. /************************************************************************/
  310. PRIVATE    time_stamp()
  311.  
  312. {    int    t, pos;
  313.     char    buf[5];
  314.  
  315.        t = time(0);
  316.        if (t - old_time >= resolution) {
  317.           window_set(text, TEXTSW_INSERTION_POINT, TEXTSW_INFINITY, 0);
  318.           pos = (int) window_get(text, TEXTSW_LENGTH);
  319.           if (pos != 0) {
  320.              window_get(text, TEXTSW_CONTENTS, pos - 1, buf, 1);
  321.              if (buf[0] != '\n')
  322.                 do_insertion("\n", 1);
  323.              }
  324.           do_insertion("\n<<< ", 5);
  325.           do_insertion(ctime(&t), 24);
  326.           do_insertion(" >>>\n", 5);
  327.           old_time = t;
  328.           }
  329. }
  330.  
  331. /************************************************************************/
  332. PRIVATE    Notify_value    input_func(me, fd)
  333.  
  334. int    *me;
  335. int    fd;
  336.  
  337. {    char    old_c, *s, *t;
  338.     f_ptr    f;
  339.     int    count, do_blink = FALSE, do_open = FALSE;
  340.     static    char    in_buf[INPUT_BUFFER_SIZE + 2];
  341.  
  342.     while ((count = read(fileno(master), in_buf, INPUT_BUFFER_SIZE)) >= 0) {
  343.        in_buf[count] = '\0';
  344.        while (s = index(in_buf, '\015')) {
  345.           strcpy(s, s + 1);
  346.           count--;
  347.           }
  348.        for (t = in_buf; *t; *s = old_c, t = s) {
  349.           if (s = index(t, '\n')) {
  350.              old_c = *++s;
  351.              *s = '\0';
  352.              }
  353.           else {
  354.              s = t + strlen(t);
  355.              old_c = '\0';
  356.              }
  357.           if (curr_filter == NULL) {
  358.              load_filters();
  359.              for (f = filters; f && f->start; f++)
  360.                 if (f->valid && match_exp(f->start_re, f->scircf, t)) {
  361.                    if (f->save) {
  362.                       do_blink = f->flash;
  363.                       beep_count = f->beep;
  364.                       do_open = f->open;
  365.                       if (f->stamp)
  366.                          time_stamp();
  367.               write_log(t);
  368.                       do_insertion(t, strlen(t));
  369.                       }
  370.                    if (f->end) {
  371.                       curr_filter = f;
  372.                       }
  373.                    break;
  374.                    }
  375.              if (f == NULL || f->start == NULL) {
  376.                 if (do_time_stamp)
  377.                    time_stamp();
  378.             write_log(t);
  379.                 do_insertion(t, strlen(t));
  380.                 do_blink = blink_icon;
  381.                 do_open = pop_open;
  382.                 beep_count = beep_amount;
  383.                 }
  384.              }
  385.           else {
  386.              if (curr_filter->save) {
  387.                 if (curr_filter->stamp)
  388.                    time_stamp();
  389.             write_log(t);
  390.             do_insertion(t, strlen(t));
  391.                 }
  392.              if (match_exp(curr_filter->end_re, curr_filter->ecircf, t))
  393.                 curr_filter = NULL;
  394.              }
  395.           }
  396.        }
  397.     window_set(text, TEXTSW_UPDATE_SCROLLBAR, 0);
  398.     if (do_open)
  399.        window_set(bf, FRAME_CLOSED, FALSE, 0);
  400.     if (do_blink)
  401.        if (window_get(bf, FRAME_CLOSED) && !blinking) {
  402.           window_set(bf, FRAME_ICON, bad, WIN_SHOW, TRUE, 0);
  403.           blinking = TRUE;
  404.           bad_is_up = TRUE;
  405.           menu_set(stop_blink, MENU_INACTIVE, FALSE, 0);
  406.           notify_set_itimer_func(bf, blink_proc, ITIMER_REAL, &timer, NULL);
  407.           }
  408.     if (beep_count > 0 || blinking)
  409.        notify_set_itimer_func(bf, blink_proc, ITIMER_REAL, &timer, NULL);
  410.     return(NOTIFY_DONE);
  411. }
  412.  
  413. /************************************************************************/
  414. /*    Routines which parse options, create windows, and main()    */
  415. /************************************************************************/
  416.  
  417. /************************************************************************/
  418. PRIVATE    parse_options(argc, argv)
  419.  
  420. int    *argc;
  421. char    **argv;
  422.  
  423. {    char    *s, c;
  424.  
  425.     strcpy(good_icon, ICON_DIRECTORY);
  426.     strcat(good_icon, GOOD_ICON);
  427.     strcpy(bad_icon, ICON_DIRECTORY);
  428.     strcat(bad_icon, BAD_ICON);
  429.     strcpy(inv_icon, ICON_DIRECTORY);
  430.     strcat(inv_icon, INVERSE_ICON);
  431.  
  432.     strcpy(filter_path, getenv("HOME"));
  433.     strcat(filter_path, "/.contool");
  434.  
  435.     while ((c = getopt(argc, argv, "b:c:d:f:g:l:no:pr:s:?", &s)) != EOF)
  436.        switch (c) {
  437.           case 'b' : strcpy(bad_icon, s);
  438.                    break;
  439.           case 'c' : strcpy(filter_path, s);
  440.                    explicit_filters = TRUE;
  441.                    break;
  442.           case 'd' : if (verify(s, "0123456789"))
  443.                       delete_amt = atoi(s);
  444.                    else {
  445.                       fprintf(stderr, "%s: invalid delete amount: %s\n", program, s);
  446.                       exit(1);
  447.                       }
  448.                    break;
  449.           case 'f' : strcpy(inv_icon, s);
  450.                    break;
  451.           case 'g' : strcpy(good_icon, s);
  452.                    break;
  453.           case 'l' : if (verify(s, "0123456789"))
  454.                       window_set(text, TEXTSW_MEMORY_MAXIMUM, (size_limit = atoi(s)) + TEXT_SIZE_FUZZ, 0);
  455.                    else {
  456.                       fprintf(stderr, "%s: invalid message limit: %s\n", program, s);
  457.                       exit(1);
  458.                       }
  459.                    break;
  460.           case 'n' : blink_icon = FALSE;
  461.                    break;
  462.           case 'o':  if ((logfile = fopen(s, "a")) == NULL) {
  463.                    fprintf(stderr, "%s : can't open logfile: %s\n", program, s);
  464.                 exit(1);
  465.                  }
  466.                  break;
  467.           case 'p' : pop_open = TRUE;
  468.                    break;
  469.           case 'r' : if (verify(s, "0123456789"))
  470.                       resolution = atoi(s);
  471.                    else {
  472.                       fprintf(stderr, "%s: invalid timestamp resolution: %s\n", program, s);
  473.                       exit(1);
  474.                       }
  475.                    break;
  476.           case 's' : if (verify(s, "0123456789"))
  477.                       beep_amount = atoi(s);
  478.                    else {
  479.                       fprintf(stderr, "%s: invalid beep count: %s\n", program, s);
  480.                       exit(1);
  481.                       }
  482.                    break;
  483.           case '?' : fprintf(stderr, ct_usage);
  484.                    exit(0);
  485.                    break;
  486.           default  : fprintf(stderr, ct_usage);
  487.                      exit(1);
  488.           }
  489. }
  490.  
  491. /************************************************************************/
  492. struct    pixrect    *load_icon(path, message)
  493.  
  494. char    *path;
  495. char    *message;
  496.  
  497. {    char    new_path[512], *real_path;
  498.  
  499.     if (access(path, R_OK) == -1) {
  500.        strcpy(new_path, ICON_DIRECTORY);
  501.        strcat(new_path, path);
  502.        if (access(new_path, R_OK) == -1) {
  503.           sprintf(message, "cannot read icon file %s", path);
  504.           return(NULL);
  505.           }
  506.        real_path = new_path;
  507.        }
  508.     else
  509.        real_path = path;
  510.     return(icon_load_mpr(real_path, message));
  511. }
  512.  
  513. /************************************************************************/
  514. PRIVATE    load_icons()
  515.  
  516. {    char    msg[IL_ERRORMSG_SIZE];
  517.  
  518.     if ((good_pr = load_icon(good_icon, msg)) == NULL) {
  519.        fprintf(stderr, "%s: %s\n", program, msg);
  520.        exit(1);
  521.        }
  522.     good = icon_create(ICON_IMAGE, good_pr,
  523.                ICON_LABEL, "",
  524.                ICON_WIDTH, good_pr->pr_size.x,
  525.                ICON_HEIGHT, good_pr->pr_size.y,
  526.                0);
  527.     icon_width = good_pr->pr_size.x;
  528.     icon_height = good_pr->pr_size.y;
  529.     if ((bad_pr = load_icon(bad_icon, msg)) == NULL) {
  530.        fprintf(stderr, "%s: %s\n", program, msg);
  531.        exit(1);
  532.        }
  533.     bad = icon_create(ICON_IMAGE, bad_pr,
  534.               ICON_LABEL, "",
  535.               ICON_WIDTH, bad_pr->pr_size.x,
  536.               ICON_HEIGHT, bad_pr->pr_size.y,
  537.               0);
  538.     if (bad_pr->pr_size.x > icon_width)
  539.        icon_width = bad_pr->pr_size.x;
  540.     if (bad_pr->pr_size.y > icon_height)
  541.        icon_height = bad_pr->pr_size.y;
  542.     if (*inv_icon == '\0')
  543.        strcpy(inv_icon, bad_icon);
  544.     if ((inv_pr = load_icon(inv_icon, msg)) == NULL) {
  545.        fprintf(stderr, "%s: %s\n", program, msg);
  546.        exit(1);
  547.        }
  548.     inverse = icon_create(ICON_IMAGE, inv_pr,
  549.                   ICON_LABEL, "",
  550.                   ICON_WIDTH, inv_pr->pr_size.x,
  551.                   ICON_HEIGHT, inv_pr->pr_size.y,
  552.                   0);
  553.     if (inv_pr->pr_size.x > icon_width)
  554.        icon_width = inv_pr->pr_size.x;
  555.     if (inv_pr->pr_size.y > icon_height)
  556.        icon_height = inv_pr->pr_size.y;
  557.     window_set(bf, FRAME_ICON, good, 0);
  558. }
  559.  
  560. /************************************************************************/
  561. main(argc, argv)
  562.  
  563. int    argc;
  564. char    **argv;
  565.  
  566. {    char    *path;
  567.     int    i;
  568.     Menu    menu;
  569.  
  570.     program = strsave(argv[0]);
  571.  
  572.     bf = window_create(NULL, FRAME, 
  573.                   FRAME_ARGC_PTR_ARGV, &argc, argv,
  574.                   FRAME_LABEL, TOOL_LABEL,
  575.                0);
  576.     text = window_create(bf, TEXTSW, 
  577.                     TEXTSW_DISABLE_CD, TRUE,
  578.                     TEXTSW_DISABLE_LOAD, TRUE, 
  579.                     TEXTSW_AGAIN_RECORDING, FALSE,
  580.                     TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
  581.                     TEXTSW_HISTORY_LIMIT, 0,
  582.                     TEXTSW_MEMORY_MAXIMUM, size_limit + TEXT_SIZE_FUZZ,
  583.                  0);
  584.     open_rect = *((Rect *) window_get(bf, FRAME_OPEN_RECT));
  585.  
  586.     argv = saveargs(argc, argv);
  587.     parse_options(&argc, argv);
  588.     if (argc != 1) {
  589.        fprintf(stderr, ct_usage);
  590.        exit(1);
  591.        }
  592.  
  593.     load_icons();
  594.  
  595.     path = open_psuedo_tty(&master, "r", &slave, "w");
  596.     if (master == NULL) {
  597.        fprintf(stderr, "%s: couldn't open any psuedo-tty\n");
  598.        exit(1);
  599.        }
  600.     if (slave == NULL) {
  601.        fprintf(stderr, "%s: couldn't open slave side of %s\n", program, path);
  602.        exit(1);
  603.        }
  604.  
  605.     i = fcntl(fileno(master), F_GETFL, 0);
  606.     i |= FNDELAY;
  607.     if (fcntl(fileno(master), F_SETFL, i) == -1) {
  608.        fprintf(stderr, "%s: could not force %s to non-blocking i/o\n", program, path);
  609.        exit(1);
  610.        }
  611.  
  612.     acquire_console(path);
  613.  
  614.     stop_blink = menu_create_item(MENU_STRING, "Stop Blinking",
  615.                       MENU_INACTIVE, TRUE,
  616.                       MENU_ACTION_PROC, stop_blinking,
  617.                       0);
  618.     menu = menu_create(MENU_APPEND_ITEM, stop_blink,
  619.                MENU_ACTION_ITEM, "Become Console", acquire_console,
  620.                MENU_ACTION_ITEM, "Clear Messages", clear_messages,
  621.                MENU_ACTION_ITEM, "Edit Filters", edit_filters,
  622.                MENU_PULLRIGHT_ITEM, "Frame", window_get(bf, WIN_MENU),
  623.                0);
  624.     window_set(bf, WIN_MENU, menu, 0);
  625.  
  626.     notify_set_input_func(bf, input_func, fileno(master));
  627.     notify_interpose_destroy_func(bf, destroy_proc);
  628.     notify_interpose_event_func(bf, close_proc, NOTIFY_SAFE);
  629.  
  630.     load_filters();
  631.  
  632.     window_main_loop(bf);
  633. }
  634.