home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / pcomm / part05 / terminal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-17  |  7.9 KB  |  365 lines

  1. /*
  2.  * Start the terminal dialogue, fork the input routine, watch for the
  3.  * hot key so we can execute an option.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <curses.h>
  8. #include <signal.h>
  9. #ifdef UNIXPC
  10. #include <sys/phone.h>
  11. #include <fcntl.h>
  12. #endif /* UNIXPC */
  13. #include "dial_dir.h"
  14. #include "modem.h"
  15. #include "param.h"
  16. #include "status.h"
  17.  
  18. terminal(input_status)
  19. int input_status;
  20. {
  21.     int i, k, cr_lf;
  22.     char c, lf=10, *strdup(), *new_dir, *change_dir();
  23.     void help_screen(), line_set(), native_shell(), load_vs();
  24.     void setup_menu(), hang_up(), input_on(), list_dir(), pexit();
  25.     void status_line(), free_ptr(), screen_dump(), input_off();
  26.  
  27.                     /* if starting out in command mode */
  28.     if (!input_status)
  29.         status_line(NULL);
  30.                     /* put the terminal in raw mode */
  31.     resetterm();
  32.     cr_lf = raw_mode();
  33.  
  34.     if (input_status)
  35.         input_on();
  36.  
  37.     while(1) {
  38.         read(0, &c, 1);
  39.                     /* is it the hot key? */
  40.         if (c == param->hot) {
  41.                     /* suspend input */
  42.             input_status = 0;
  43.             if (status->pid != -1)
  44.                 kill(status->pid, SIGINT);
  45.  
  46.             /*
  47.              * Put in terminal in the curses mode and add
  48.              * the status line at the bottom.
  49.              */
  50.             fixterm();
  51.             status_line(NULL);
  52. #ifndef OLDCURSES
  53.             keypad(stdscr, 1);
  54. #endif /* OLDCURSES */
  55.             i = wgetch(stdscr);
  56.                     /* map the hot key to -1 */
  57.             if (i == param->hot)
  58.                 i = -1;
  59.             /*
  60.              * Load the virtual screen from the file.  On
  61.              * very busy systems, the file might not "appear"
  62.              * fast enough for this routine to detect it.
  63.              * Or worse, it may contain partially written
  64.              * information.
  65.              */
  66.             load_vs();
  67.                     /* look for options */
  68.             k = -1;
  69.             switch (i) {
  70.                 case -1:    /* 2 'hots' means send 1 */
  71.                     k = param->hot;
  72.                     break;
  73.                 case '0':    /* help screen */
  74.                     help_screen(param->ascii_hot, status->fd);
  75.                     break;
  76.                 case 'd':
  77.                 case 'D':    /* dialing directory */
  78.                     if (dial_menu())
  79.                         input_status = dial_win();
  80.                     break;
  81.                 case 'r':
  82.                 case 'R':    /* redial */
  83.                     if (redial(status->fd))
  84.                         input_status = dial_win();
  85.                     break;
  86.                 case 'p':
  87.                 case 'P':    /* line settings */
  88.                     if (line_set_menu(status->fd)) {
  89.                         line_set();
  90.                     }
  91.                     break;
  92.                 case 'x':
  93.                 case 'X':    /* exit */
  94.                     pexit(status->fd);
  95.                     break;
  96.                 case '4':    /* Unix gateway */
  97.                     native_shell();
  98.                     break;
  99.                 case 'i':
  100.                 case 'I':    /* Program info screen */
  101.                     info(status->fd);
  102.                     break;
  103.                 case 's':    /* setup menu */
  104.                 case 'S':
  105.                     setup_menu(status->fd);
  106.                     break;
  107.                 case 'c':    /* clear the screen */
  108.                 case 'C':
  109.                     unlink(status->vs_path);
  110.                     clear();
  111.                     clear_absolute(stdscr);
  112.                     break;
  113.                 case 'b':
  114.                 case 'B':    /* Change directory */
  115.                     if ((new_dir = change_dir(status->fd)) != NULL) {
  116.                         chdir(new_dir);
  117.                         free_ptr(new_dir);
  118.                     }
  119.                     break;
  120.                 case 'e':
  121.                 case 'E':    /* toggle duplex */
  122.                     if (dir->duplex[dir->d_cur] == 'F')
  123.                         dir->duplex[dir->d_cur] = 'H';
  124.                     else
  125.                         dir->duplex[dir->d_cur] = 'F';
  126.                     line_set();
  127.  
  128.                         /* show changes */
  129.                     status_line(NULL);
  130.                     k = wait_key(stdscr, 2);
  131.                     break;
  132.                 case 'h':
  133.                 case 'H':    /* hang up phone */
  134.                     hang_up(1);
  135.                     input_off();
  136.                     break;
  137.                 case 'l':
  138.                 case 'L':    /* toggle printer */
  139.                     status->print = status->print ? 0 : 1;
  140.                     if (status->pid != -1)
  141.                         kill(status->pid, SIGUSR2);
  142.  
  143.                         /* show changes */
  144.                     status_line(NULL);
  145.                     k = wait_key(stdscr, 2);
  146.                     break;
  147.                 case '3':    /* toggle CR  CR/LF */
  148.                     if (!strcmp(param->cr_in, "CR"))
  149.                         param->cr_in = strdup("CR/LF");
  150.                     else
  151.                         param->cr_in = strdup("CR");
  152.                     input_off();
  153.                     input_status = 1;
  154.  
  155.                         /* show changes */
  156.                     status_line(NULL);
  157.                     k = wait_key(stdscr, 2);
  158.                     break;
  159.                 case '7':    /* break key */
  160.                     if (status->fd != -1)
  161.                         ioctl(status->fd, TCSBRK, 0);
  162.  
  163.                     status_line("   break");
  164.                     break;
  165. #ifndef OLDCURSES
  166.                 case KEY_UP:
  167. #endif /* OLDCURSES */
  168.                 case 'u':
  169.                 case 'U':    /* send files */
  170.                     input_status = xfer_menu(1);
  171.                     break;
  172. #ifndef OLDCURSES
  173.                 case KEY_DOWN:
  174.                 case '\n':
  175. #endif /* OLDCURSES */
  176.                 case 'n':
  177.                 case 'N':    /* receive files */
  178.                     input_status = xfer_menu(0);
  179.                     break;
  180.                 case 'f':
  181.                 case 'F':    /* list directory */
  182.                     list_dir(status->fd);
  183.                     break;
  184.                 case 'g':    /* screen dump */
  185.                 case 'G':
  186.                     screen_dump();
  187.                     status_line(" screen dump");
  188.                     k = wait_key(stdscr, 2);
  189.                     break;
  190.                 case '1':    /* data logging */
  191.                     input_status = data_logging(status->fd);
  192.                     break;
  193.                 case '2':    /* toggle log */
  194.                     if (!strcmp(status->log_path, "NOT_DEFINED")) {
  195.                         beep();
  196.                         status_line(" no log file");
  197.                         k = wait_key(stdscr, 2);
  198.                         break;
  199.                     }
  200.                     status->log = status->log ? 0 : 1;
  201.                     if (status->pid != -1)
  202.                         kill(status->pid, SIGUSR1);
  203.     
  204.                         /* show changes */
  205.                     status_line(NULL);
  206.                     k = wait_key(stdscr, 2);
  207.                     break;
  208.                 default:
  209.                     fputc(7, stderr);
  210.                     break;
  211.             }
  212.  
  213.             /*
  214.              * Repaint the stdscr (if we are already talking),
  215.              * get the terminal out of the curses mode and
  216.              * into the raw mode.
  217.              */
  218.             if (status->fd != -1) {
  219.                 touchwin(stdscr);
  220.                 refresh();
  221.             }
  222.             resetterm();
  223.             cr_lf = raw_mode();
  224.                     /* re-start input routine */
  225.             if (input_status)
  226.                 input_on();
  227.             else {
  228.                     /* un-suspend (is that a word?) */
  229.                 if (status->pid != -1)
  230.                     kill(status->pid, SIGINT);
  231.             }
  232.             /*
  233.              * If you pressed a key during one of the sleeping
  234.              * periods (typically the delay to see the status
  235.              * line change), let the keyboard value fall thru
  236.              * to the write() below.
  237.              */
  238.             if (k == -1)
  239.                 continue;
  240.             c = k;
  241.         }
  242.         write(status->fd, &c, 1);
  243.                     /* map cr to cr_lf ? */
  244.         if (cr_lf)
  245.             write(status->fd, &lf, 1);
  246.     }
  247. }
  248.  
  249. /*
  250.  * Put the terminal in the raw mode.  We've divided up the responsibility
  251.  * for the line settings options between the serial port and the tty driver
  252.  * for the stdin and stdout.  The return code is the cr_lf mapping.
  253.  */
  254.  
  255. int
  256. raw_mode()
  257. {
  258.     int ret_code;
  259.     struct termio tbuf;
  260.  
  261.     ioctl(0, TCGETA, &tbuf);
  262.  
  263.     tbuf.c_cc[4] = 1;        /* VMIN */
  264.     tbuf.c_cc[5] = 0;        /* VTIME */
  265.     tbuf.c_iflag = 0;
  266.     tbuf.c_oflag = 0;
  267.     tbuf.c_lflag = 0;
  268.  
  269.     /*
  270.      * Some of the output processing options have to be faked...
  271.      * Unfortunately, adding a LF to CR is one of them.
  272.      */
  273.     ret_code = 0;
  274.     if (!strcmp(param->cr_out, "CR/LF"))
  275.         ret_code++;
  276.                     /* duplex */
  277.     if (dir->duplex[dir->d_cur] == 'H')
  278.         tbuf.c_lflag = ECHO;
  279.  
  280.     ioctl(0, TCSETA, &tbuf);
  281.     ioctl(0, TCFLSH, 2);
  282.     return(ret_code);
  283. }
  284.  
  285. /*
  286.  * Fire up the input routine...
  287.  */
  288.  
  289. void
  290. input_on()
  291. {
  292.     int pid, add_lf;
  293.                     /* if no tty, or already on */
  294.     if (status->pid != -1 || status->fd == -1)
  295.         return;
  296.                     /* input cr translations */
  297.     add_lf = !strcmp(param->cr_in, "CR/LF");
  298.  
  299.                     /* fork the input routine */
  300.     if (!(pid = fork()))
  301.         input(status->fd, add_lf, status->log, status->print,
  302.          LINES, COLS, status->vs_path, status->log_path);
  303.  
  304.     status->pid = pid;
  305.     return;
  306. }
  307.  
  308. /*
  309.  * shut it down...
  310.  */
  311.  
  312. void
  313. input_off()
  314. {
  315.     if (status->pid != -1) {
  316.         kill(status->pid, SIGTERM);
  317.         status->pid = -1;
  318.     }
  319.     return;
  320. }
  321.  
  322. /*
  323.  * Hang up the phone but remain in the pcomm command state.
  324.  */
  325.  
  326. void
  327. hang_up(verbose)
  328. int verbose;
  329. {
  330.     void send_str(), status_line();
  331. #ifdef UNIXPC
  332.     char buf[20], *strcpy(), *strcat();
  333. #endif /* UNIXPC */
  334.  
  335.                     /* anything to hang up? */
  336.     if (modem->m_cur == -1)
  337.         return;
  338.  
  339.     if (verbose)
  340.         status_line("disconnecting");
  341.                     /* special case for OBM */
  342. #ifdef UNIXPC
  343.     if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
  344.         ioctl(status->fd, PIOCDISC);
  345.         /*
  346.          * The PIOCDISC ioctl prevents writes on the file descriptor!
  347.          * No other phone(7) ioctl can fix it...  Whatever it does, it
  348.          * seems to escape detection with PIOCGETA and TCGETA.  The
  349.          * best I can do is close the descriptor and start over.
  350.          */
  351.         close(status->fd);
  352.         strcpy(buf, "/dev/");
  353.         strcat(buf, modem->tty[modem->t_cur]);
  354.         status->fd = open(buf, O_RDWR|O_NDELAY);
  355.         fcntl(status->fd, F_SETFL, fcntl(status->fd, F_GETFL, 0) & ~O_NDELAY);
  356.     }
  357.     else
  358. #endif /* UNIXPC */
  359.         send_str(modem->hangup[modem->m_cur]);
  360.  
  361.     if (verbose)
  362.         status_line(NULL);
  363.     return;
  364. }
  365.