home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / pcomm2 / part06 / terminal.c < prev   
Encoding:
C/C++ Source or Header  |  1988-09-14  |  9.5 KB  |  465 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. #include "config.h"
  10. #ifdef OLDCURSES
  11. #include <termio.h>
  12. #endif /* OLDCURSES */
  13. #ifdef UNIXPC
  14. #include <sys/phone.h>
  15. #include <fcntl.h>
  16. #endif /* UNIXPC */
  17. #include "dial_dir.h"
  18. #include "misc.h"
  19. #include "modem.h"
  20. #include "param.h"
  21. #include "status.h"
  22.  
  23. static int pid = -1;
  24.  
  25. terminal(input_status)
  26. int input_status;
  27. {
  28.     extern int fd;
  29.     int i, k, cr_lf;
  30.     char c, lf=10, *strdup();
  31.     void help_screen(), line_set(), n_shell(), load_vs(), send_str();
  32.     void hang_up(), do_input(), list_dir(), pexit(), zap_vs();
  33.     void st_line(), chg_dir(), screen_dump(), input_off(), suspend();
  34.     void info(), term_mode();
  35.  
  36.                     /* if starting out in command mode */
  37.     if (!input_status)
  38.         st_line("");
  39.                     /* put stdin/stdout in terminal mode */
  40.     resetterm();
  41.     term_mode();
  42.  
  43.     if (input_status)
  44.         do_input();
  45.  
  46.     while (1) {
  47.         read(0, &c, 1);
  48.                     /* is it the hot key? */
  49.         if (c == param->hot) {
  50.                     /* suspend input */
  51.             input_status = 0;
  52.             suspend(1);
  53.  
  54.             /*
  55.              * Put in terminal in the curses mode, load the
  56.              * virtual screen and add the status line at the bottom.
  57.              */
  58.             fixterm();
  59.             load_vs();
  60.             st_line("");
  61. #ifndef OLDCURSES
  62.             keypad(stdscr, TRUE);
  63. #endif /* OLDCURSES */
  64.             i = wgetch(stdscr);
  65.                     /* map an additional hot key to -1 */
  66.             if (i == param->hot)
  67.                 i = -1;
  68.                     /* look for options */
  69.             k = -1;
  70.             switch (i) {
  71.                 case -1:    /* 2 "hots" means send 1 */
  72.                     k = param->hot;
  73.                     break;
  74.                 case '0':    /* help screen */
  75.                     help_screen(param->ascii_hot);
  76.                     break;
  77.                 case 'd':
  78.                 case 'D':    /* dialing directory */
  79.                     if (dial_menu())
  80.                         input_status = dial_win();
  81.                     break;
  82.                 case 'r':
  83.                 case 'R':    /* redial */
  84.                     if (redial())
  85.                         input_status = dial_win();
  86.                     break;
  87.                 case 'm':
  88.                 case 'M':    /* keyboard macros */
  89.                     macro();
  90.                     break;
  91.                 case 'p':
  92.                 case 'P':    /* line settings */
  93.                     if (ls_menu())
  94.                         line_set();
  95.                     break;
  96.                 case 'x':
  97.                 case 'X':    /* exit */
  98.                     pexit();
  99.                     break;
  100.                 case '4':    /* Unix gateway */
  101.                     n_shell();
  102.                     break;
  103.                 case 'i':
  104.                 case 'I':    /* Program info screen */
  105.                     info(0);
  106.                     break;
  107.                 case 's':    /* setup menu */
  108.                 case 'S':
  109.                     input_status = setup_menu();
  110.                     break;
  111.                 case 'c':    /* clear the screen */
  112.                 case 'C':
  113.                     zap_vs();
  114.                     erase();
  115.                     break;
  116.                 case 'b':
  117.                 case 'B':    /* Change directory */
  118.                     chg_dir();
  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.  
  127.                         /* show changes */
  128.                     st_line("");
  129.                     k = wait_key(stdscr, 2);
  130.                     break;
  131.                 case 'h':
  132.                 case 'H':    /* hang up phone */
  133.                     hang_up(1);
  134.                     input_off();
  135.                     break;
  136.                 case 'l':
  137.                 case 'L':    /* toggle printer */
  138.                     status->print = status->print ? 0 : 1;
  139. #ifndef SHAREDMEM
  140.                     if (pid != -1)
  141.                         kill(pid, SIGUSR2);
  142. #endif /* SHAREDMEM */
  143.                         /* show changes */
  144.                     st_line("");
  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.                         status->add_lf = 1;
  151.                     }
  152.                     else {
  153.                         param->cr_in = strdup("CR");
  154.                         status->add_lf = 0;
  155.                     }
  156. #ifndef SHAREDMEM
  157.                     input_off();
  158.                     input_status++;
  159. #endif /* SHAREDMEM */
  160.                         /* show changes */
  161.                     st_line("");
  162.                     k = wait_key(stdscr, 2);
  163.                     break;
  164.                 case '7':    /* break key */
  165.                     if (fd != -1)
  166.                         ioctl(fd, TCSBRK, 0);
  167.  
  168.                     st_line("   break");
  169.                     break;
  170. #ifndef OLDCURSES
  171.                 case KEY_UP:
  172. #endif /* OLDCURSES */
  173.                 case 'u':
  174.                 case 'U':    /* send files */
  175.                     input_status = xfer_menu(1);
  176.                     break;
  177. #ifndef OLDCURSES
  178.                 case KEY_DOWN:
  179.                 case '\n':
  180. #endif /* OLDCURSES */
  181.                 case 'n':
  182.                 case 'N':    /* receive files */
  183.                     input_status = xfer_menu(0);
  184.                     break;
  185.                 case 't':
  186.                 case 'T':
  187.                     input_status = pass_thru();
  188.                     break;
  189.                 case 'f':
  190.                 case 'F':    /* list directory */
  191.                     list_dir();
  192.                     break;
  193.                 case 'g':    /* screen dump */
  194.                 case 'G':
  195.                     screen_dump();
  196.                     st_line(" screen dump");
  197.                     k = wait_key(stdscr, 2);
  198.                     break;
  199.                 case '1':    /* data logging */
  200.                     input_status = data_logging();
  201.                     break;
  202.                 case '2':    /* toggle log */
  203.                     if (!strcmp(status->log_path, "NOT_DEFINED")) {
  204.                         beep();
  205.                         st_line(" no log file");
  206.                         k = wait_key(stdscr, 2);
  207.                         break;
  208.                     }
  209.                     status->log = status->log ? 0 : 1;
  210. #ifndef SHAREDMEM
  211.                     if (pid != -1)
  212.                         kill(pid, SIGUSR1);
  213. #endif /* SHAREDMEM */
  214.                         /* show changes */
  215.                     st_line("");
  216.                     k = wait_key(stdscr, 2);
  217.                     break;
  218.                 /*
  219.                  * The following are the keyboard macros
  220.                  * corresponding to the shifted number keys.
  221.                  * (Too many keys... [control] [A] [shift] [1]
  222.                  * is hardly a shortcut!)
  223.                  */
  224.                 case '!':
  225.                     send_str(param->mac_1);
  226.                     break;
  227.                 case '@':
  228.                     send_str(param->mac_2);
  229.                     break;
  230.                 case '#':
  231.                     send_str(param->mac_3);
  232.                     break;
  233.                 case '$':
  234.                     send_str(param->mac_4);
  235.                     break;
  236.                 case '%':
  237.                     send_str(param->mac_5);
  238.                     break;
  239.                 case '^':
  240.                     send_str(param->mac_6);
  241.                     break;
  242.                 case '&':
  243.                     send_str(param->mac_7);
  244.                     break;
  245.                 case '*':
  246.                     send_str(param->mac_8);
  247.                     break;
  248.                 case '(':
  249.                     send_str(param->mac_9);
  250.                     break;
  251.                 case ')':
  252.                     send_str(param->mac_0);
  253.                     break;
  254.                 default:
  255.                     fputc(BEL, stderr);
  256.                     break;
  257.             }
  258.  
  259.             /*
  260.              * Repaint the stdscr (if we are already talking),
  261.              * get the stdin/stdout out of the curses mode and
  262.              * into the terminal mode.
  263.              */
  264.             if (fd != -1) {
  265.                 touchwin(stdscr);
  266.                 refresh();
  267.             }
  268.             resetterm();
  269.             term_mode();
  270.  
  271.             /*
  272.              * Some of the output processing options have to be
  273.              * faked...  Unfortunately, adding a LF to CR on
  274.              * output is one of them.
  275.              */
  276.             cr_lf = !strcmp(param->cr_out, "CR/LF");
  277.  
  278.                     /* re-start input routine */
  279.             if (input_status)
  280.                 do_input();
  281.             else
  282.                 suspend(0);
  283.  
  284.             /*
  285.              * If you pressed a key during one of the sleeping
  286.              * periods (typically the delay to see the status
  287.              * line change), let the keyboard value fall thru
  288.              * to the write() below.
  289.              */
  290.             if (k == -1)
  291.                 continue;
  292.             c = k;
  293.         }
  294.                     /* ignore errors if fd == -1 */
  295.         write(fd, &c, 1);
  296.                     /* map cr to cr_lf? */
  297.         if (c == '\r' && cr_lf)
  298.             write(fd, &lf, 1);
  299.     }
  300. }
  301.  
  302. /*
  303.  * Put the stdin/stdout in terminal mode.  We've divided up the
  304.  * responsibility for the line settings options between the serial port
  305.  * and the stdin and stdout.
  306.  */
  307.  
  308. void
  309. term_mode()
  310. {
  311.     struct termio tbuf;
  312.  
  313.     ioctl(0, TCGETA, &tbuf);
  314.  
  315.     tbuf.c_cc[4] = 1;        /* VMIN */
  316.     tbuf.c_cc[5] = 0;        /* VTIME */
  317.     tbuf.c_iflag = 0;
  318.     tbuf.c_oflag = 0;
  319.     tbuf.c_lflag = 0;
  320.                     /* duplex */
  321.     if (dir->duplex[dir->d_cur] == 'H')
  322.         tbuf.c_lflag = ECHO;
  323.  
  324.     ioctl(0, TCSETA, &tbuf);
  325.     ioctl(0, TCFLSH, 2);
  326.     return;
  327. }
  328.  
  329. /*
  330.  * Fire up the input routine...
  331.  */
  332.  
  333. static void
  334. do_input()
  335. {
  336.     extern int fd;
  337.     void error_win();
  338.     char first[(sizeof(int)*8)+1];
  339. #ifdef SHAREDMEM
  340.     extern int shm_id;
  341. #else /* SHAREDMEM */
  342.     char add_lf[2], log[2], print[2];
  343. #endif /* SHAREDMEM */
  344.                     /* if no TTY, or already on */
  345.     if (pid != -1 || fd == -1)
  346.         return;
  347.  
  348.     status->fd = fd;
  349.     if (!strcmp(param->cr_in, "CR/LF"))
  350.         status->add_lf = 1;
  351.     else
  352.         status->add_lf = 0;
  353.  
  354. #ifdef SHAREDMEM
  355.     sprintf(first, "%d", shm_id);
  356. #else /* SHAREDMEM */
  357.     sprintf(first, "%d", status->fd);
  358.     sprintf(add_lf, "%d", status->add_lf);
  359.     sprintf(log, "%d", status->log);
  360.     sprintf(print, "%d", status->print);
  361. #endif /* SHAREDMEM */
  362.  
  363.                     /* fork the input routine */
  364.     if (!(pid = fork())) {
  365. #ifdef SETUGID
  366.         setuid(getuid());
  367.         setgid(getgid());
  368. #endif /* SETUGID */
  369. #ifdef SHAREDMEM
  370.         execlp("pcomm_input", "pcomm_input", first, (char *) 0);
  371. #else /* SHAREDMEM */
  372.         execlp("pcomm_input", "pcomm_input", first, add_lf, log,
  373.          print, status->log_path, status->vs_path, (char *) 0);
  374. #endif /* SHAREDMEM */
  375.         error_win(1, "Cannot find (or execute) the 'pcomm_input' program", "");
  376.     }
  377.  
  378.     return;
  379. }
  380.  
  381. /*
  382.  * shut it down...
  383.  */
  384.  
  385. void
  386. input_off()
  387. {
  388.     if (pid != -1) {
  389.         kill(pid, SIGTERM);
  390.         pid = -1;
  391.     }
  392.     return;
  393. }
  394.  
  395. /*
  396.  * Hang up the phone but remain in the Pcomm command state.  Uses the
  397.  * hang_up string only, does *not* drop the DTR!
  398.  */
  399.  
  400. void
  401. hang_up(verbose)
  402. int verbose;
  403. {
  404.     extern int fd;
  405.     void send_str(), st_line(), line_set();
  406. #ifdef UNIXPC
  407.     char buf[40], *strcpy(), *ttyname();
  408. #endif /* UNIXPC */
  409.                     /* sanity checking */
  410.     if (modem == NULL)
  411.         return;
  412.                     /* anything to hang up? */
  413.     if (modem->m_cur == -1 || fd == -1)
  414.         return;
  415.  
  416.     if (verbose)
  417.         st_line("disconnecting");
  418.                     /* special case for OBM */
  419. #ifdef UNIXPC
  420.     if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
  421.         ioctl(fd, PIOCDISC);
  422.         /*
  423.          * The PIOCDISC ioctl screws up the file descriptor!!!
  424.          * No other phone(7) ioctl can fix it.  Whatever it does,
  425.          * it seems to escape detection with PIOCGETA and TCGETA.
  426.          * The best I can do is close the port and start over.
  427.          */
  428.         strcpy(buf, ttyname(fd));
  429.         close(fd);
  430.         fd = open(buf, O_RDWR|O_NDELAY);
  431.         fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
  432.         line_set();
  433.     }
  434.     else
  435. #endif /* UNIXPC */
  436.         send_str(modem->hang_up[modem->m_cur]);
  437.  
  438.     if (verbose)
  439.         st_line("");
  440.     return;
  441. }
  442.  
  443. /*
  444.  * Suspend or un-suspend the input routine.  The argument is used in
  445.  * non-shared memory configurations to give the vs_path file a fighting
  446.  * chance of being written to disk before load_vs() reads it.
  447.  */
  448.  
  449. /*ARGSUSED*/
  450. void
  451. suspend(on)
  452. int on;
  453. {
  454.     unsigned int sleep();
  455.  
  456.     if (pid == -1)
  457.         return;
  458.     kill(pid, SIGINT);
  459. #ifndef SHAREDMEM
  460.     if (on)
  461.         sleep(1);
  462. #endif /* SHAREDMEM */
  463.     return;
  464. }
  465.