home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3598 / xcterm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-11  |  5.7 KB  |  307 lines

  1. /*    xcterm.c -- terminal modemodule for XC
  2.     This file uses 4-character tabstops
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <ctype.h>
  9. #include <signal.h>
  10. #include <setjmp.h>
  11. #include <termio.h>
  12. #include "xc.h"
  13.  
  14. #define ENDCHAR        (('X' & 0x1f) + 128)    /* Exit terminal mode */
  15. #define TOGCHAR        (('T' & 0x1f) + 128)    /* Toggle capture buffer */
  16. #define DIVCHAR        (('F' & 0x1f) + 128)    /* Send file through modem */
  17. #define DIALCHR        (('D' & 0x1f) + 128)    /* Dial from phonelist */
  18. #define HUPCHAR        (('H' & 0x1f) + 128)    /* Hang up modem */
  19. #define SCRPCHR        (('S' & 0x1f) + 128)    /* Execute script file */
  20. #define BRKCHAR        (('B' & 0x1f) + 128)    /* modem BREAK character */
  21. #define QUITCHR        (('Q' & 0x1f) + 128)    /* close and leave XC */
  22.  
  23. char captfile[SM_BUFF] = CAPTFILE,    /* capture file's name */
  24.      phonefile[SM_BUFF] = PHFILE;    /* phone number file's name */
  25.  
  26. static FILE    *cfp,            /* capture file pointer */
  27.             *fp;            /* file to transmit */
  28.  
  29. static    int    child_pid;        /* ID of child process */
  30. static    void (*oldvec)();
  31. static    short doneyet_dd;
  32. static    jmp_buf rtm, stop;
  33. char    ddsname[SM_BUFF];
  34. short    s_flag, capture = FALSE;
  35.  
  36. extern char *strstr();
  37. extern short autoflag, hdplxflag, nlmode;
  38.  
  39. /* toggle capture status */
  40. static void toggle()
  41. {
  42.     if (capture) {
  43.         fclose(cfp);
  44.         capture = FALSE;
  45.         sprintf(Msg,"\"%s\" closed for capturing",captfile);
  46.         S2;
  47.     } else {
  48.         if ((cfp = fopen(captfile, "a")) == NULLF) {
  49.             sprintf(Msg,"Can't open \"%s\" for capturing",captfile);
  50.             S2;
  51.         } else {
  52.             capture = TRUE;
  53.             sprintf(Msg,"capturing to \"%s\"",captfile);
  54.             setbuf(cfp, NULLS);
  55.             S2;
  56.         }
  57.     }
  58.     sleep(1);
  59.  
  60.     signal(SIGUSR2, toggle);    /* set signal for next toggle */
  61. }
  62.  
  63. /*    cleanup, flush and exit */
  64. static void cleanup()
  65. {
  66.     if (capture) {
  67.         fclose(cfp);
  68.         sprintf(Msg,"\"%s\" closed for capturing",captfile);
  69.         S2;
  70.     }
  71.  
  72.     exit(0);
  73. }
  74.  
  75. void newbmask()
  76. {
  77.     if (bitmask == 0xff)
  78.         bitmask = 0x7f;
  79.     else
  80.         bitmask = 0xff;
  81.  
  82.     if (child_pid)
  83.         kill(child_pid, SIGUSR1);
  84. }
  85.  
  86. static void cisbmode()
  87. {
  88.     cismode = 2;
  89.     signal(SIGCLD, SIG_IGN);
  90.  
  91.     longjmp(rtm,1);
  92. }
  93.  
  94. static void end_divert()
  95. {
  96.     show_abort();
  97.     fclose(fp);
  98.     signal(SIGINT, oldvec);
  99.     longjmp(stop,1);
  100. }
  101.  
  102. /*    Divert file into input stream, with delay after each newline. */
  103. void divert(script)
  104. short script;
  105. {
  106.     int c, i = 0;
  107.  
  108.     if (!script) {
  109.         fputc('\n',tfp);
  110.         show(-1,"File?");
  111.         getline();
  112.         getword();
  113.     }
  114.     if (word[0] == '\0')
  115.         return;
  116.     if ((fp = fopen(word, "r")) == NULLF) {
  117.         sprintf(Msg,"Can't access '%s'",word);
  118.         S2;
  119.         return;
  120.     }
  121.  
  122.     oldvec = signal(SIGINT,end_divert);
  123.     if (setjmp(stop))
  124.         return;
  125.  
  126.     while ((c = getc(fp)) != EOF) {
  127.         if (c != '\n') {
  128.             send_mbyte(c);
  129.             i++;
  130.         }
  131.         else {
  132.             i = (CBAUD-cbaud)*100 + 5*i + 50;
  133.             send_mbyte(nlmode ? '\r' : '\n');
  134.             if (script)
  135.                 k_waitfor(-i, "");
  136.             else
  137.                 msecs(i);
  138.             i = 0;
  139.         }
  140.     }
  141.     fclose(fp);
  142.     signal(SIGINT,oldvec);
  143. }
  144.  
  145. void terminal(todir)
  146. short todir;
  147. {
  148.     register c;
  149.  
  150.     doneyet_dd = FALSE;
  151.     intdel(FALSE);
  152. Reterm:
  153.     setjmp(rtm);
  154.  
  155.     if (cismode > 1 || doneyet_dd) {
  156.         if (doneyet_dd)
  157.             doneyet_dd = FALSE;
  158.         return;
  159.     }
  160.  
  161.     s_flag = FALSE;        /* reset scripting flag */
  162.  
  163.     if (!todir)
  164.         show(2,"Entering Terminal Mode");
  165.     /* split into read and write processes */
  166.     if ((child_pid = forkem()) == 0) {
  167.         /* child, read proc: read from port and write to tty */
  168.         cfp = NULLF;
  169.         if (autoflag && !todir)
  170.             toggle();
  171.         signal(SIGUSR2, toggle);
  172.         signal(SIGTERM, cleanup);
  173.         signal(SIGUSR1, newbmask);
  174.         while (1) {
  175.             while ((c = read_mbyte(0)) == -1)
  176.                 ;
  177.             if (cismode && c == ENQ) {
  178.                 cismode = 2;
  179.                 cleanup();
  180.             }
  181.             fputc(c,tfp);
  182.             if (capture && c != '\r')
  183.                 fputc(c,cfp);
  184.         }
  185.         /*NOTREACHED*/
  186.     }
  187.     /* parent, write proc: read from tty and write to port */
  188.     signal(SIGCLD, cisbmode);
  189.  
  190.     if (todir) goto dialdir;
  191.     do {
  192.         switch (c = getconchr()) {
  193.         case TOGCHAR:        /* signal child to toggle buffer */
  194.             kill(child_pid, SIGUSR2);
  195.             break;
  196.  
  197.         case DIVCHAR:        /* divert a file through modem port */
  198.             intdel(TRUE);
  199.             divert(FALSE);
  200.             intdel(FALSE);
  201.             break;
  202.  
  203.         case BRKCHAR:
  204.             xmitbrk();
  205.             break;
  206.  
  207.         case SCRPCHR:        /* execute a script file */
  208.             if (get_script()==FAILURE)
  209.                 break;
  210.             s_flag = TRUE;
  211.             goto filicide;
  212.  
  213.         case DIALCHR:        /* select and dial a phone number */
  214. dialdir:
  215.             doneyet_dd = TRUE;
  216.             if ((dial_dir()==FAILURE && todir) || s_flag)
  217.                 goto filicide;
  218.             if (autoflag)
  219.                 toggle();
  220.             break;
  221.  
  222.         case ENDCHAR:        /* signal child to cleanup and exit */
  223. filicide:
  224.             c = ENDCHAR;
  225.             signal(SIGCLD, SIG_IGN);
  226.             kill(child_pid, SIGTERM);
  227.             break;
  228.         
  229.         case QUITCHR:
  230.             signal(SIGCLD, SIG_IGN);
  231.             kill(child_pid, SIGTERM);
  232.             s_exit();
  233.             break;
  234.  
  235.         case HUPCHAR:        /* Hangup */
  236.             hangup();
  237.             break;
  238.  
  239.         case '\n':        /* See if NL translation in effect */
  240.             if (nlmode)
  241.                 c = '\r';
  242.  
  243.         default:    /* just send the character to the port */
  244.             send_mbyte(c);
  245.             if (hdplxflag)
  246.                 fputc(c,tfp);
  247.             break;
  248.         }
  249.         todir = FALSE;
  250.     } while (c != ENDCHAR);
  251.  
  252.     while (wait((int *) 0) >= 0)    /* wait for the read process to die */
  253.         ;
  254.  
  255.     if (s_flag) {
  256.         do_script(ddsname);
  257.         goto Reterm;
  258.     }
  259.  
  260.     reterm = FALSE;
  261. }
  262.  
  263. /*    The next three functions are only run by the port read process (child).
  264.     They handle the capture file.
  265. */
  266. /*    Select a script file. If the file exists, execute it, otherwise
  267.     exit with a non-zero return.
  268. */
  269. static get_script()
  270. {
  271.     fputc('\n',tfp);
  272.     show(-1,"Enter script file:");
  273.     getline();
  274.     if (line[0] == '\0') {
  275.         fputc('\n',tfp);
  276.         show(1,"Script file not specified");
  277.         return FAILURE;
  278.     }
  279.     linkflag = FALSE;
  280.     getword();
  281.     sprintf(ddsname,"%s",word);
  282.     return SUCCESS;
  283. }
  284.  
  285. static getconchr()
  286. {
  287.     int c, tc;
  288.  
  289.     if ((c = trminp()) == MY_ESC) {
  290.         switch (c = ((tc = trminp()) & 0x1f) + 128) {
  291.         case ENDCHAR:
  292.         case TOGCHAR:
  293.         case BRKCHAR:
  294.         case DIVCHAR:
  295.         case DIALCHR:
  296.         case HUPCHAR:
  297.         case SCRPCHR:
  298.         case QUITCHR:
  299.             break;
  300.  
  301.         default:
  302.             c = tc;
  303.         }
  304.     }
  305.     return c;
  306. }
  307.