home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / prog1 / zmnp11.lzh / CU.C next >
C/C++ Source or Header  |  1990-02-08  |  19KB  |  745 lines

  1. /****************************************************************************
  2. *    Author        :    G Todd                                                    *
  3. *    Language     :    Turbo C 2.0                                                *
  4. *    Logfile        :    cu.c                                                    *
  5. *    Project        :    Comms library.                                            *
  6. *    Date         :    19 Jan 90                                                *
  7. *    Revision     :    1.1        GT    Originate.                                    *
  8. *****************************************************************************
  9. *    Purpose        :    Testbed/demo for comms library.                            *
  10. *                :    Copyright 1990 Giles Todd.                                *
  11. ****************************************************************************/
  12.  
  13. #include    <stdio.h>
  14. #include    <stdlib.h>
  15. #include    <conio.h>
  16. #include    <dos.h>
  17. #include    <string.h>
  18. #include    <signal.h>
  19. #include    "zmnp.h"
  20.  
  21. typedef enum { FALSE, TRUE } BOOLEAN;
  22. typedef unsigned char BYTE;
  23. typedef unsigned short int WORD;
  24.  
  25. #ifdef    __TURBOC__
  26. extern unsigned _stklen = 16384;            /* big stack                    */
  27. #endif
  28.  
  29.  
  30. /****************************************************************************
  31. *    Function prototypes.                                                    *
  32. ****************************************************************************/
  33.  
  34. int main (int argc, char *argv[]);
  35. static void usage (char *progname);
  36. static void send_char (int c);
  37. static void badarg (char *progname, char *arg);
  38. static void mnperror (int errcode);
  39. static void send_files (void);
  40. static void send_command (void);
  41. static void get_files (void);
  42. #ifdef __TURBOC__
  43. static void openwindow (void);
  44. static void reporter (int type, void *data);
  45. void tout (char *s);
  46. static void closewindow (void);
  47. #endif
  48.  
  49.  
  50. /****************************************************************************
  51. *    Global and static data.                                                    *
  52. ****************************************************************************/
  53.  
  54. static BOOLEAN mnp_on = FALSE;            /* TRUE = MNP running                */
  55. static char z_down[] = "**\030B00000000000000\r\n\021";
  56. static char hst_mnp_off[] = "AT&M0\r";    /* HST 'no MNP' string                */
  57. static BYTE rx_buf[BUFSIZ];                /* Receive buffer.                    */
  58.  
  59.  
  60. /****************************************************************************
  61. *    Program code.                                                            *
  62. ****************************************************************************/
  63.  
  64. int main (int argc, char *argv[])
  65.     {
  66.     int rate = 5;                        /* 2400 bps                            */
  67.     int data = 8;                        /* 8 data bits                        */
  68.     int parity = 0;                        /* no parity                        */
  69.     int stop = 1;                        /* 1 stop bit                        */
  70.     int port = 1;                        /* COM1                                */
  71.     int handshake = 1;                    /* RTS/CTS                            */
  72.     unsigned short tx_free;                /* free in Tx buffer                */
  73.     unsigned short rx_rdy;                /* ready in Rx buffer                */
  74.     int c;                                /* for keyboard input                */
  75.     BOOLEAN esc_flag = FALSE;            /* TRUE: last char was '~'            */
  76.     int i;                                /* loop counter                        */
  77.     union REGS regs;                    /* for ioctl call                    */
  78.     int mnpmode = -1;                    /* -1 = no MNP, 0 = orig, 1 = ans    */
  79.     struct link_stat_blk mnpstat;        /* MNP status                        */
  80.     long speed;                            /* line speed                        */
  81.     int zmatch = 0;                        /* match count for z_down string    */
  82.     void (*sig_ptr) (int);                /* old SIGINT handler                */
  83.     
  84.     /* Set 'raw' mode for stdin and stdout. */
  85.  
  86.     for (i = 0; i < 2; i++)
  87.         {
  88.         regs.x.ax = 0x4400;                /* get device info                    */
  89.         regs.x.bx = i;                    /* handle                            */
  90.         intdos (®s, ®s);
  91.         regs.x.dx |= 0x20;                /* set 'raw' mode                    */
  92.         regs.x.ax = 0x4401;                /* set device info                    */
  93.         regs.x.bx = i;
  94.         intdos (®s, ®s);
  95.         }
  96.  
  97.     /* Look for options. */
  98.  
  99.     if (argc > 1)
  100.         {
  101.         for (i = 1; i < argc; i++)
  102.             {
  103.             if (argv[i][0] != '-')
  104.                 badarg (argv[0], argv[i]);
  105.  
  106.             switch (argv[i][1])
  107.                 {
  108.                 case 'o':                    /* MNP originate                */
  109.                     mnpmode = 0;
  110.                     break;
  111.  
  112.                 case 'a':                    /* MNP answer                    */
  113.                     mnpmode = 1;
  114.                     break;
  115.  
  116.                 case 'p':                    /* COM port                        */
  117.                     sscanf (&argv[i][2], "%d", &port);
  118.                     if (port != 1 && port != 2)
  119.                         badarg (argv[0], argv[i]);
  120.  
  121.                     break;
  122.  
  123.                 case 's':                    /* line speed                    */
  124.                     sscanf (&argv[i][2], "%ld", &speed);
  125.  
  126.                     /* Select baud rate token from speed. Roll on ANSI C. */
  127.  
  128.                     if (speed == 110L)
  129.                         rate = 1;
  130.                     else if (speed == 300L)
  131.                         rate = 2;
  132.                     else if (speed == 600L)
  133.                         rate = 3;
  134.                     else if (speed == 1200L)
  135.                         rate = 4;
  136.                     else if (speed == 2400L)
  137.                         rate = 5;
  138.                     else if (speed == 4800L)
  139.                         rate = 6;
  140.                     else if (speed == 9600L)
  141.                         rate = 7;
  142.                     else if (speed == 19200L)
  143.                         rate = 8;
  144.                     else if (speed == 38400L)
  145.                         rate = 9;
  146.                     else if (speed == 56000L)
  147.                         rate = 10;
  148.                     else if (speed == 115200L)
  149.                         rate = 11;
  150.                     else
  151.                         badarg (argv[0], argv[i]);
  152.  
  153.                     break;
  154.                     
  155.                 default:
  156.                     badarg (argv[0], argv[i]);
  157.                 }    /* switch (argv[i][1]) */
  158.  
  159.             }    /* for (i = 1; i < argc, i++) */
  160.             
  161.         }    /* if (argc > 1) */
  162.         
  163.     /* Install isrs and init 8250. */
  164.  
  165.     c = connect (rate, data, parity, stop, port, handshake);
  166.     if (c != 0)
  167.         {
  168.         switch (c)
  169.             {
  170.             case -64:
  171.                 fprintf (stderr, "Bad rate %d\n", rate);
  172.                 break;
  173.  
  174.             case -65:
  175.                 fprintf (stderr, "Bad data length %d\n", data);
  176.                 break;
  177.  
  178.             case -66:
  179.                 fprintf (stderr, "Bad parity %d\n", parity);
  180.                 break;
  181.  
  182.             case -67:
  183.                 fprintf (stderr, "Bad number of stop bits %d\n", stop);
  184.                 break;
  185.  
  186.             case -68:
  187.                 fprintf (stderr, "Bad port number %d\n", port);
  188.                 break;
  189.  
  190.             case -69:
  191.                 fprintf (stderr, "Bad handshake flag %d\n", handshake);
  192.                 break;
  193.  
  194.             default:
  195.                 fprintf (stderr, "Unknown error code %d\n", c);
  196.                 break;
  197.             }    /* switch (c) */
  198.  
  199.         exit (c);
  200.         }    /* if (c != 0) */
  201.  
  202.     /* Save SIGINT handler. */
  203.  
  204.     sig_ptr = signal (SIGINT, SIG_IGN);
  205.     
  206.     /* Switch off HST MNP */
  207.  
  208.     send ((unsigned char *) hst_mnp_off, strlen (hst_mnp_off));
  209.  
  210.     /* Main polling loop */
  211.  
  212.     while (1)
  213.         {
  214.         if (mnpmode != -1 && !mnp_on)
  215.             {
  216.             /* Attempt MNP connection when carrier detected. */
  217.  
  218.             if ((modemstat () & 0x80) != 0)
  219.                 {
  220.                 /* We have carrier - try to establish MNP link.*/
  221.  
  222.                 c = mnpconnect (mnpmode);
  223.                 switch (c)
  224.                     {
  225.                     case 0:                    /* success                        */
  226.                         mnp_on = TRUE;
  227.                         fputs ("MNP level 2\n", stderr);
  228.                         break;
  229.  
  230.                     case -64:
  231.                         fputs ("MNP failure, unknown error\n", stderr);
  232.                         break;
  233.  
  234.                     case -65:
  235.                         fputs ("MNP failure, timeout\n", stderr);
  236.                         break;
  237.  
  238.                     case -66:
  239.                         fputs ("MNP failure, no carrier\n", stderr);
  240.                         break;
  241.  
  242.                     case -70:
  243.                         fputs ("MNP failure, incompatible ARQ\n", stderr);
  244.                         break;
  245.  
  246.                     case -72:
  247.                         fputs ("MNP failure, remote protocol error\n", stderr);
  248.                         break;
  249.  
  250.                     default:
  251.                         fprintf (stderr, "Unknown error code %d\n", c);
  252.                         break;
  253.                     }    /* switch (c) */
  254.  
  255.                 }    /* if ((modemstat () & 0x80) != 0) */
  256.  
  257.             }    /* if (mnpmode != -1 && !mnp_on) */
  258.  
  259.         /* Poll characters received from remote. */
  260.         
  261.         c = 0;
  262.         if (mnp_on)                            /* MNP connection?                */
  263.             {
  264.             mnpstatus (&mnpstat);            /* get MNP status                */
  265.             if (mnpstat.r_count != 0)
  266.                 {
  267.                 c = mnpreceive (rx_buf, (mnpstat.r_count > sizeof (rx_buf))
  268.                                         ? sizeof (rx_buf)
  269.                                         : mnpstat.r_count);
  270.                 if (c < 0)
  271.                     {
  272.                     mnperror (c);
  273.                     break;
  274.                     }
  275.                     
  276.                 for (i = 0; i < c; i++)
  277.                     putchar (rx_buf[i]);    /* and echo                        */
  278.  
  279.                 }
  280.  
  281.             if (mnpstat.l_status == 0)
  282.                 {
  283.                 fputs ("MNP link broken\n", stderr);
  284.                 mnpdisconnect ();
  285.                 hangup ();
  286.                 mnp_on = FALSE;
  287.                 }
  288.                 
  289.             }    /* if (mnp_on) */
  290.         else
  291.             {
  292.             bufstat (&tx_free, &rx_rdy);    /* anything from remote?        */
  293.             if (rx_rdy != 0)
  294.                 {
  295.                 c = receive (rx_buf, (rx_rdy > sizeof (rx_buf))
  296.                                      ? sizeof (rx_buf)
  297.                                      : rx_rdy);
  298.                 for (i = 0; i < c; i++)
  299.                     putchar (rx_buf[i]);    /* and echo                        */
  300.                 
  301.                 }
  302.  
  303.             }
  304.  
  305.         /* Check for ZMODEM download. */
  306.  
  307.         for (i = 0; i < c; i++)
  308.             {
  309.             if (zmatch == strlen (z_down) - 1)
  310.                 {
  311.                 get_files ();                /* start ZMODEM download        */
  312.                 zmatch = 0;
  313.                 }
  314.                 
  315.             if (rx_buf[i] != z_down[zmatch])
  316.                 zmatch = 0;
  317.             else
  318.                 zmatch++;
  319.  
  320.             }
  321.             
  322.             
  323.         /* Poll user input. */
  324.         
  325.         if (kbhit () != 0)
  326.             {
  327.             c = getch ();                    /* get user input                */
  328.                 
  329.             if (c == '~' && !esc_flag)
  330.                 {
  331.                 esc_flag = TRUE;            /* possible user escape            */
  332.                 continue;
  333.                 }
  334.                 
  335.             /* interpret any user escape */
  336.  
  337.             if (esc_flag)
  338.                 {
  339.                 esc_flag = FALSE;
  340.                 if (c == '.')
  341.                     break;                    /* ~. means exit                */
  342.  
  343.                 switch (c)
  344.                     {
  345.                     case 'c':                /* remote command                */
  346.                         send_command ();
  347.                         break;
  348.                         
  349.                     case 's':                /* send files                    */
  350.                         send_files ();
  351.                         break;
  352.  
  353.                     case 'r':                /* receive files                */
  354.                         get_files ();
  355.                         break;
  356.  
  357.                     default:
  358.                         send_char ('~');    /* not escape sequence            */
  359.                         send_char (c);
  360.                         break;
  361.                     }    /* switch (c) */
  362.                     
  363.                 }    /* if (esc_flag) */
  364.             else
  365.                 send_char (c);                /* send data to remote             */
  366.                 
  367.             }    /* if (kbhit () != 0) */
  368.  
  369.         }    /* while (1) */
  370.  
  371.     /* User wants to quit */
  372.  
  373.     if (mnp_on)
  374.         mnpdisconnect ();
  375.         
  376.     disconnect ();                            /* put back original state        */
  377.  
  378.     signal (SIGINT, sig_ptr);
  379.     return (0);                                /* exit                            */
  380.     }    /* int main (int argc, char *argv[]) */
  381.  
  382.  
  383. /****************************************************************************
  384. *    mnperror                                                                *
  385. *    Display MNP send/receive error message.                                    *
  386. ****************************************************************************/
  387.  
  388. static void mnperror (errcode)
  389.     {
  390.     switch (errcode)
  391.         {
  392.         case -64:
  393.             fputs ("Link terminated, retransmission limit exceeded\n", stderr);
  394.             break;
  395.  
  396.         case -65:
  397.             fputs ("Link terminated, unable to send\n", stderr);
  398.             break;
  399.  
  400.         case -66:
  401.             fputs ("Link terminated, no carrier\n", stderr);
  402.             break;
  403.  
  404.         case -67:
  405.             fputs ("Link terminated, remote disconnect\n", stderr);
  406.             break;
  407.  
  408.         default:
  409.             fprintf (stderr, "Link terminated, unknown error %d\n", errcode);
  410.             break;
  411.         }    /* switch (errcode) */
  412.  
  413.     }    /* static void mnperror (errcode) */
  414.     
  415.  
  416. /****************************************************************************
  417. *    badarg                                                                    *
  418. *    There was a bad command line argument.  Print error message and exit.    *
  419. ****************************************************************************/
  420.  
  421. static void badarg (char *progname, char *arg)
  422.     {
  423.     fprintf (stderr, "Bad argument %s\n", arg);
  424.     usage (progname);
  425.     }    /* static void badarg (char *progname, char *arg) */
  426.     
  427.  
  428. /****************************************************************************
  429. *    send_char                                                                *
  430. *    Send a character to remote.                                                *
  431. ****************************************************************************/
  432.  
  433. static void send_char (int c)
  434.     {
  435.     int result;                                /* from mnpsend                    */
  436.     
  437.     if (mnp_on)                                /* MNP connection?                */
  438.         {
  439.         while ((result = mnpsend ((unsigned char *) &c, 1)) != 1)
  440.             {
  441.             if (result < 0)
  442.                 {
  443.                 mnperror (result);
  444.                 break;
  445.                 }
  446.  
  447.             }
  448.  
  449.         }
  450.     else
  451.         {
  452.         while (send ((unsigned char *) &c, 1) != 1)
  453.             ;
  454.  
  455.         }
  456.  
  457.     }    /* static void send_char (int c) */
  458.     
  459.  
  460. /****************************************************************************
  461. *    usage                                                                    *
  462. *    Display usage message and exit.                                            *
  463. ****************************************************************************/
  464.  
  465. static void usage (char *progname)
  466.     {
  467.     fprintf (stderr, "Usage: %s [options]\n"
  468.                      "Options are:\n"
  469.                      "-o        MNP originate mode\n"
  470.                      "-a        MNP answer mode\n"
  471.                      "-p<port>    Use COM<port> (default COM1)\n"
  472.                      "-s<speed>    Bps (default 300)\n",
  473.                      progname);
  474.     exit (1);
  475.     }    /* static void usage (char *progname) */
  476.  
  477.  
  478. /****************************************************************************
  479. *    send_files                                                                *
  480. *    Send file(s) via ZMODEM.                                                *
  481. ****************************************************************************/
  482.  
  483. static void send_files (void)
  484.     {
  485.     char *filenames[5];                    /* max 4 files                        */
  486.     int i;                                /* loop counter                        */
  487.     char s[65];                            /* one filename                        */
  488.  
  489.     /* Gather filenames - wildcards not supported (use findfirst and findnext
  490.      * for wildcard support).
  491.      */
  492.      
  493.     for (i = 0; i < 4; i++)
  494.         {
  495.         printf ("\nFilename (<enter> only when done): ");
  496.         gets (s);
  497.         if (strlen (s) == 0)
  498.             {
  499.             filenames[i] = "";
  500.             break;
  501.             }
  502.  
  503.         filenames[i] = malloc (strlen (s) + 1);
  504.         strcpy (filenames[i], s);
  505.         }
  506.  
  507.     putc ('\n', stdout);
  508.     filenames[4] = "";                    /* ensure last is ""                */
  509.  
  510.     /* Send the file(s) using ZMODEM, binary xfer, 32 bit CRC, debug info,
  511.      * default reporting.
  512.      */
  513.  
  514. #ifdef __TURBOC__
  515.     openwindow ();
  516.     i = sendfile ('z', "by", filenames, reporter);
  517.     closewindow ();
  518.     switch (i)
  519. #else
  520.     switch (i = sendfile ('z', "by", filenames, NULL))
  521. #endif
  522.         {
  523.         case 0:
  524.             fputs ("File(s) sent ok\n", stderr);
  525.             return;
  526.  
  527.         case -1:
  528.             fputs ("Invalid ZMODEM option\n", stderr);
  529.             return;
  530.  
  531.         case -2:
  532.             fputs ("User abort\n", stderr);
  533.             return;
  534.  
  535.         case -3:
  536.             fputs ("No carrier\n", stderr);
  537.             return;
  538.  
  539.         default:
  540.             fprintf (stderr, "Unknown error code %d\n", i);
  541.             return;
  542.         }    /* switch (i = sendfile ('z', "by", filenames, NULL)) */
  543.         
  544.     }    /* static void send_files (void) */
  545.  
  546.  
  547. /****************************************************************************
  548. *    send_command                                                            *
  549. *    Send remote command via ZMODEM.                                            *
  550. ****************************************************************************/
  551.  
  552. static void send_command (void)
  553.     {
  554.     char s[132];                        /* command text                        */
  555.     int cmdlen;                            /* command length                    */
  556.     char *filenames[1];                    /* dummy filenames parameter        */
  557.     
  558.     /* Enter command. */
  559.  
  560.     printf ("Remote command: ");
  561.     gets (s + 2);
  562.     *s = 'i';                            /* no wait for completion            */
  563.     s[1] = '#';                            /* turn into option string            */
  564.     cmdlen = strlen (s);
  565.     s[cmdlen] = '#';
  566.     s[cmdlen + 1] = '\0';
  567.     filenames[0] = "";                    /* dummy filenames parameter        */
  568.     
  569.     /* Send the command. */
  570.  
  571. #ifdef __TURBOC__
  572.     openwindow ();
  573.     cmdlen = sendfile ('z', s, filenames, reporter);
  574.     closewindow ();
  575.     switch (cmdlen)
  576. #else
  577.     switch (cmdlen = sendfile ('z', s, filenames, NULL))
  578. #endif
  579.         {
  580.         case 0:
  581.             fputs ("Command sent ok\n", stderr);
  582.             return;
  583.  
  584.         case -1:
  585.             fputs ("Invalid ZMODEM option\n", stderr);
  586.             return;
  587.  
  588.         case -2:
  589.             fputs ("User abort\n", stderr);
  590.             return;
  591.  
  592.         case -3:
  593.             fputs ("No carrier\n", stderr);
  594.             return;
  595.  
  596.         default:
  597.             fprintf (stderr, "Unknown error code %d\n", cmdlen);
  598.             return;
  599.         }    /* switch (cmdlen = sendfile ('z', "by", filenames, NULL)) */
  600.     
  601.     }    /* static void send_command (void) */
  602.  
  603.  
  604. /****************************************************************************
  605. *    get_files                                                                *
  606. *    Get file(s) using ZMODEM.                                                *
  607. ****************************************************************************/
  608.  
  609. static void get_files (void)
  610.     {
  611.     int i;
  612.     
  613. #ifdef __TURBOC__
  614.     openwindow ();
  615.     i = getfile ('z', "b", NULL, reporter);
  616.     closewindow ();
  617.     switch (i)
  618. #else
  619.     switch (i = getfile ('z', "b", NULL, NULL))
  620. #endif
  621.         {
  622.         case 0:
  623.             fputs ("File(s) received ok\n", stderr);
  624.             return;
  625.  
  626.         case -1:
  627.             fputs ("Invalid ZMODEM option\n", stderr);
  628.             return;
  629.  
  630.         case -2:
  631.             fputs ("User abort\n", stderr);
  632.             return;
  633.  
  634.         case -3:
  635.             fputs ("No carrier\n", stderr);
  636.             return;
  637.  
  638.         default:
  639.             fprintf (stderr, "Unknown error code %d\n", i);
  640.             return;
  641.         }    /* switch (i = sendfile ('z', "by", filenames, NULL)) */
  642.         
  643.     }    /* static void get_files (void) */
  644.  
  645.  
  646. #ifdef __TURBOC__
  647.  
  648. static BYTE savescreen[61 * 5 * 2];        /* save area for screen window        */
  649. static struct text_info oldscr;            /* old coordinates etc                */
  650.  
  651. /****************************************************************************
  652. *    openwindow                                                                *
  653. *    Set up the window for the ZMODEM report function.                        *
  654. ****************************************************************************/
  655.  
  656. void openwindow (void)
  657.     {
  658.     gettextinfo (&oldscr);                /* save old cursor etc                */
  659.     gettext (11, 11, 71, 15, savescreen);    /* save what's there            */
  660.     window (11, 11, 70, 15);            /* set window boundaries            */
  661.     clrscr ();
  662.     window (11, 11, 71, 15);            /* while drawing box                */
  663.     gotoxy (1, 1);
  664.     cprintf ("╔══════════════════════════════════════════════════════════╗");
  665.     gotoxy (1, 2);
  666.     cprintf ("║                                                          ║");
  667.     gotoxy (1, 3);
  668.     cprintf ("║                                                          ║");
  669.     gotoxy (1, 4);
  670.     cprintf ("║                                                          ║");
  671.     gotoxy (1, 5);
  672.     cprintf ("╚══════════════════════════════════════════════════════════╝");
  673.     window (12, 12, 69, 14);            /* text boundaries                    */
  674.     }    /* void openwindow (void) */
  675.  
  676.  
  677. /****************************************************************************
  678. *    closewindow                                                                *
  679. *    Restore screen to its previous state.                                    *
  680. ****************************************************************************/
  681.  
  682. void closewindow (void)
  683.     {
  684.     puttext (11, 11, 71, 15, savescreen);    /* put back what was there        */
  685.     window (oldscr.winleft, oldscr.wintop, oldscr.winright, oldscr.winbottom);
  686.     gotoxy (oldscr.curx, oldscr.cury);
  687.     }    /* void closewindow (void) */
  688.  
  689.  
  690. /****************************************************************************
  691. *    tout                                                                    *
  692. *    Display <s> in the current window, filtering line feeds.                *
  693. ****************************************************************************/
  694.  
  695. void tout (char *s)
  696.     {
  697.     int c;
  698.     
  699.     while ((c = *s++) != '\0')
  700.         if (c != '\n')
  701.             putch (c);
  702.  
  703.     }    /* void tout (char *s) */
  704.     
  705.  
  706. /****************************************************************************
  707. *    reporter                                                                *
  708. *    Do report functions for ZMODEM.                                            *
  709. ****************************************************************************/
  710.  
  711. void reporter (int type, void *data)
  712.     {
  713.     char buf[128];                        /* for received text                */
  714.     
  715.     switch (type)
  716.         {
  717.         case 0:                            /* filename                            */
  718.             gotoxy (1, 1);
  719.             clreol ();
  720.             sprintf (buf, "FILE: %s", data);
  721.             tout (buf);
  722.             return;
  723.  
  724.         case 1:                            /* transfer count                    */
  725.             gotoxy (1, 2);
  726.             clreol ();
  727.             sprintf (buf, "%7ld", *((long *) data));
  728.             tout (buf);
  729.             return;
  730.  
  731.         case 2:                            /* other text                        */
  732.             gotoxy (1, 3);
  733.             clreol ();
  734.             sprintf (buf, "%s", data);
  735.             tout (buf);
  736.             return;
  737.  
  738.         default:
  739.             fprintf (stderr, "reporter: unknown type %d\n", type);
  740.             return;
  741.         }    /* switch (type) */
  742.  
  743.     }    /* void reporter (int type, void *data) */
  744. #endif
  745.