home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc072.zip / ckdcon.c < prev    next >
C/C++ Source or Header  |  1988-08-16  |  14KB  |  429 lines

  1. char *connv = "Connect Command for Data General, V4C(015) 11 May 87";
  2.  
  3. /*  C K U C O N  --  Dumb terminal connection to remote system, for Unix  */
  4. /*
  5.  This module should work under all versions of Unix.  It calls externally
  6.  defined system-dependent functions for i/o, but depends upon the existence
  7.  of the fork() function.
  8.  
  9.  Author: Frank da Cruz (SY.FDC@CU20B),
  10.  Columbia University Center for Computing Activities, January 1985.
  11.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  12.  Permission is granted to any individual or institution to use, copy, or
  13.  redistribute this software so long as it is not sold for profit, provided this
  14.  copyright notice is retained. 
  15.  
  16.  Enhanced by H. Fischer to detect when child process (modem reader)
  17.  reports that the communications line has been broken and hang up.
  18.  Also enhanced to allow escaping from connect state to command
  19.  interpreter, to allow sending/receiving without breaking connection.
  20.   
  21.  This module was adapted to the Data General computers by:
  22.  
  23.     Phil Julian, SAS Institute, Inc., Box 8000, Cary, NC 27512-8000
  24.   
  25.  The idea for conect(), talker(), and listener() (which is integral 
  26.  to conect()) came from the Kermit for MV/UX, whose authors are:
  27.  
  28.     Jim Guyton, Rand Corporation
  29.     Walter Underwood, Ford Aerospace
  30.     David Ragozin, Univ. Washinton
  31.     John Sambrook, Univ. Washington, Bioengineering.
  32.  
  33. */
  34.  
  35. #include <stdio.h>
  36. #include <ctype.h>            /* Character types */
  37. #include "ckcdeb.h"
  38. #include "ckcker.h"
  39. #include <signal.h>
  40. #include <setjmp.h>
  41.  
  42. #ifndef SIGUSR1
  43. #define SIGUSR1 16
  44. #endif
  45.  
  46. #ifdef datageneral
  47. #include <sgtty.h>                /* Set/Get tty modes */
  48. #include <multitask.h>                                                          
  49. #include <packets:common.h>
  50. #include <packets/normal_io.h>
  51.  
  52. /* Delimiter table -- defaults to CR only */
  53. extern short idel_tbl[7] = {0x4,0,0,0,0,0,0};
  54.  
  55. /* Globals and defines for DG multi-tasking connect command */
  56. void talker();                 /* talker sub-task */                        
  57. #define  TALKID     17         /* task id of talker task */                   
  58. #define  TALKPRI    200        /* priority of talker (was 2) */
  59. #define  STACK      0          /* default stack size (was 1024) */
  60.  
  61. extern int ttyfd,ttyfdout;
  62. #define MAXINBUF 2048
  63. static int inbufsize = MAXINBUF;       /* current size of input buffer */
  64. extern long times();
  65. #endif datageneral
  66.  
  67. extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp;
  68. extern int errno;
  69.  
  70. extern char ttname[], sesfil[];
  71. extern char dopar();
  72.  
  73. int i, active;                /* variables global to this module */
  74. char *chstr();
  75. char temp[50];
  76.  
  77. #define LBUFL 200            /* line buffer */
  78. char lbuf[LBUFL];
  79.  
  80. /* connect state parent/child communication signal handlers */
  81.  
  82. static jmp_buf env_con;            /* envir ptr for connect errors */
  83.  
  84. static
  85. conn_int() {                /* modem read failure handler, */
  86.     longjmp(env_con,1);            /* notifies parent process to stop */
  87. }
  88.  
  89. /*  c o n e c t  --  perform terminal connection  */
  90.  
  91. conect() {
  92.     int pid,             /* process id of child (modem reader) */
  93.     parent_id,        /* process id of parent (keyboard reader) */
  94.     n;
  95.     int c;            /* c is a character, but must be signed 
  96.                    integer to pass thru -1, which is the
  97.                    modem disconnection signal, and is
  98.                    different from the character 0377 */
  99.     char errmsg[50], *erp;
  100.  
  101.     if (!local) {
  102.         printf("Sorry, you must 'set line' first\n");
  103.         return(-2);
  104.     }
  105.     if (speed < 0) {
  106.         printf("Sorry, you must 'set speed' first\n");
  107.         return(-2);
  108.         }
  109.     if ((escape < 0) || (escape > 0177)) {
  110.         printf("Your escape character is not ASCII - %d\n",escape);
  111.         return(-2);
  112.     }
  113.     if (ttopen(ttname,&local,mdmtyp) < 0) {
  114.         erp = errmsg;
  115.         sprintf(erp,"Sorry, can't open %s",ttname);
  116.         perror(errmsg);
  117.         return(-2);
  118.         }
  119.         printf("Connecting thru %s, speed %d.\r\n",ttname,speed);
  120.     printf("The escape character is %s (%d).\r\n",chstr(escape),escape);
  121.     printf("Type the escape character followed by C to get back,\r\n");
  122.     printf("or followed by ? to see other options.\r\n");
  123.     if (seslog) printf("(Session logged to %s.)\r\n",sesfil);
  124.  
  125. /* condition console terminal and communication line */        
  126.  
  127.         if (conbin(escape) < 0) {
  128.         printf("Sorry, can't condition console terminal\n");
  129.         return(-2);
  130.         }
  131.     if (ttvt(speed,flow) < 0) {
  132.         conres();
  133.         printf("Sorry, can't condition communication line\n");
  134.         return(-2);
  135.         }
  136.  
  137. /* cont'd... */
  138.  
  139. /* ...connect, cont'd */
  140.  
  141.  
  142. #ifdef datageneral
  143.                                                                                 
  144. /* The channel must be duplicated in order to allow simultaneous writes to
  145.    it  from the 'talker' task.  Otherwise, the 'listener' hogs the channel
  146.    and prevents any access.  ttopen() opens up two channels for this
  147.    purpose.
  148.    
  149.    This code was adapted from the Kermit written for MV/UX, dgmvux.c .
  150.    I have kept the same name as some of the original variables and some
  151.    of the original comments (with a "**" line prefix).  But I have 
  152.    changed the code alot.  I do appreciate the idea, and have listed 
  153.    the names of the MV/UX Kermit authors:
  154.    
  155.         Jim Guyton, Rand Corporation
  156.         Walter Underwood, Ford Aerospace
  157.         David Ragozin, Univ. Washinton
  158.         John Sambrook, Univ. Washington, Bioengineering.
  159.         
  160. */
  161. /*                                                                              
  162. **    Under MV/UX a true fork() call does not exist; however, we can            
  163. **    create multiple asynchronous tasks with a program.  We create             
  164. **    two sub-tasks, ``listener'' and ``talker'' to handle the data             
  165. **    communication.  For the main task to regain control one or both           
  166. **    of the tasks must set the terminate flag; therefore it is cleared         
  167. **    before either task is initiated.                                          
  168. */                                                                              
  169.     active = 1;                                                              
  170.  
  171.     setto(channel(ttyfdout),60); /* Set timeouts to 60 seconds */
  172.     setto(channel(ttyfd),2);     /* Set timeouts to 2 (not 10) seconds */
  173.     
  174.     mfinit(stdout,1);      /* Protect output to terminal screen */
  175.  
  176.     if (mtask(talker, STACK, TALKID, TALKPRI) != 0)                             
  177.     {                                                                           
  178.         perror("Can't initiate talker task.");
  179.         return(-2);
  180.     }                                                                           
  181.  
  182.     while (active) {
  183.         /* The original listener() task is inserted here.  This leaves the 
  184.          * talker task as the only multiple task.
  185.          */
  186.         int i;
  187.         char buffer[MAXINBUF+1];                /* I/O buffer for output */
  188.         inbufsize = MAXINBUF-1;
  189.  
  190.         c = dgncinb(ttyfd,&buffer,inbufsize);
  191.          
  192.         if (c < 0) { /* Comm line hangup detected */
  193.               if (errno == 9999)  /* Modem disconnected, or in progress */
  194.                    printf("\r\nCommunications disconnect ");
  195.               else {
  196.                    /* Data overrun error or timeout */
  197.                    if ((c == -EROVR) || (c == -2)) continue;
  198.                    perror("\r\nCan't get character");
  199.               }
  200.               active=0;                         /* wait to die */
  201.               continue;
  202.         } /* c < 0 */
  203.         buffer[c] = '\0';    /* Null terminate based on length of data */
  204.         for (i = 0; i < c; i++) { buffer[i] &= 0177; }
  205.         conxo(c,buffer);                        /* Output */
  206.         if (seslog) zsoutx(ZSFILE,buffer,c);      /* Log */
  207.     }  /* while active */
  208.                                                             
  209.     printf("\r\n[Back at Local System]\n");
  210.     mfinit(stdout,0);      /* Un-protect output to terminal screen */
  211.  
  212. #else
  213.     parent_id = getpid();        /* get parent id for signalling */
  214.     pid = fork();            /* All ok, make a fork */
  215.     if (pid == -1) {
  216.         conres();            /* Reset the console. */
  217.         perror("Can't create keyboard fork");
  218.         printf("[Back at Local System]\n");
  219.         return(0);
  220.     }
  221.         
  222.     if (pid) {            
  223.       active = 1;            /* This fork reads, sends keystrokes */
  224.       if (!setjmp(env_con)) {    /* comm error in child process */
  225.         signal(SIGUSR1,conn_int);    /* routine for child process exit */
  226.         while (active) {
  227.         c = coninc(0) & 0177;    /* Get character from keyboard */
  228.         if (c == escape) {       /* Look for escape char */
  229.             c = coninc(0) & 0177;   /* Got esc, get its arg */
  230.             doesc(c);            /* And process it */
  231.         } else {        /* Ordinary character */
  232.             if (ttoc(dopar(c)) > -1) {
  233.                 if (duplex) {    /* Half duplex? */
  234.                 conoc(c);    /* Yes, also echo it. */
  235.                 if (seslog)     /* And maybe log it. */
  236.                     if (zchout(ZSFILE,c) < 0) seslog = 0;
  237.             }
  238.                     } else {
  239.             perror("\r\nCan't send character");
  240.             active = 0;
  241.             }
  242.         }
  243.           }
  244.             }                /* Come here on death of child */
  245.         kill(pid,9);        /* Done, kill inferior fork. */
  246.  
  247.         wait(0);            /* Wait till gone. */
  248.         conres();            /* Reset the console. */
  249.         printf("\r\n[Back at Local System]\n");
  250.         return(0);
  251.  
  252.     } else {            /* Inferior reads, prints port input */
  253.  
  254.         while (1) {            /* Fresh read, wait for a character */
  255.         if ((c = ttinc(0)) < 0) { /* Comm line hangup detected */
  256.             if (errno == 9999)    /* this value set by ckutio.c myread */
  257.              printf("\r\nCommunications disconnect ");
  258.             else perror("\r\nCan't get character");
  259.             kill(parent_id,SIGUSR1);    /* notify parent. */
  260.             pause();        /* Wait to be killed by parent. */
  261.                 }
  262.         c &= 0177;        /* Got a char, strip parity, etc */
  263.         conoc(c);        /* Put it on the screen. */
  264.         if (seslog) zchout(ZSFILE,c);    /* If logging, log it. */
  265.         while ((n = ttchk()) > 0) {    /* Any more left in buffer? */
  266.             if (n > LBUFL) n = LBUFL;   /* Get them all at once. */
  267.             if ((n = ttxin(n,lbuf)) > 0) {
  268.             for (i = 0; i < n; i++) lbuf[i] &= 0177;   /* Strip */
  269.  
  270.             conxo(n,lbuf);                               /* Output */
  271.             if (seslog) zsoutx(ZSFILE,lbuf,n);         /* Log */
  272.             }
  273.             }
  274.         }
  275.         }
  276. #endif
  277. }
  278.  
  279. #ifdef datageneral
  280.  
  281.                                                                                 
  282. /**               
  283.  **  t a l k e r 
  284.  **                                                                             
  285.  ** Special MV/UX sub-task to send keyboard characters to remote system.        
  286.  **                                                                             
  287.  **/
  288.                                                                                 
  289. void talker()
  290. {                                                                               
  291.      int c;            /* c is a character, but must be signed 
  292.                    integer to pass thru -1, which is the
  293.                    modem disconnection signal, and is
  294.                    different from the character 0377 */
  295.      char ch;
  296.      int n;
  297.      
  298.      /* Code was extracted from the 'child' process code in conect() */
  299.      while (active) {
  300.     c = coninc(0) & 0177;       /* Get character from keyboard */
  301.         if (c == escape) {          /* Look for escape char */
  302.         c = coninc(0) & 0177;   /* Got esc, get its arg */
  303.         doesc(c);            /* And process it */
  304.     } else {            /* Ordinary character */
  305.              if (ttoc(dopar(c)) > -1) {
  306.              if (duplex) {      /* Half duplex? */
  307.              conoc(c);        /* Yes, also echo it. */
  308.                      if (seslog)    /* And maybe log it. */
  309.              if (zchout(ZSFILE,c) < 0) seslog = 0;
  310.          }
  311.              } else {
  312.          perror("\r\nCan't send character");
  313.          active = 0;
  314.            }
  315.           }
  316.      }
  317.      conres();            /* Reset the console. */
  318. }                                                                   
  319. #endif datageneral
  320.  
  321.  
  322. /*  H C O N N E  --  Give help message for connect.  */
  323.  
  324. hconne() {
  325.     int c;
  326.  
  327.     static char *hlpmsg[] = {"\
  328. \r\nC to close the connection, or:",
  329. "\r\n  0 (zero) to send a null",
  330. "\r\n  B to send a BREAK",
  331. "\r\n  H to hangup and close connection",
  332. "\r\n  S for status",
  333. "\r\n  ? for help",
  334. "\r\n escape character twice to send the escape character.\r\n\r\n",
  335. "" };
  336.  
  337.     conola(hlpmsg);            /* Print the help message. */
  338.     conol("Command>");            /* Prompt for command. */
  339.     c = coninc(0);
  340.     conoc(c);                /* Echo it. */
  341.     conoll("");
  342.     c &= 0177;                /* Strip any parity. */
  343.     return(c);                /* Return it. */
  344. }
  345.  
  346.  
  347. /*  C H S T R  --  Make a printable string out of a character  */
  348.  
  349. char *
  350. chstr(c) int c; {
  351.     static char s[8];
  352.     char *cp = s;
  353.  
  354.     if (c < SP) {
  355.     sprintf(cp,"CTRL-%c",ctl(c));
  356.     } else sprintf(cp,"'%c'\n",c);
  357.     cp = s;
  358.     return(cp);
  359.  
  360. }
  361.  
  362. /*  D O E S C  --  Process an escape character argument  */
  363.  
  364. doesc(c) char c; {
  365.     CHAR d;
  366.   
  367.     c &= 0177;
  368.     while (1) {
  369.     if (c == escape) {        /* Send escape character */
  370.         d = dopar(c); ttoc(d); return;
  371.         } else                /* Or else look it up below. */
  372.         if (isupper(c)) c = tolower(c);
  373.  
  374.     switch (c) {
  375.  
  376.     case 'c':            /* Close connection */
  377.     case '\03':
  378.         active = 0; conol("\r\n"); return;
  379.  
  380.     case 'b':            /* Send a BREAK signal */
  381.     case '\02':
  382.         ttsndb(); return;
  383.  
  384.     case 'h':            /* Hangup */
  385.     case '\010':
  386.  
  387.         tthang(); active = 0; conol("\r\n"); return;
  388.  
  389.     case 's':            /* Status */
  390.         conol("\r\nConnected thru ");
  391.         conol(ttname);
  392.         if (speed >= 0) {
  393.         sprintf(temp,", speed %d",speed); conol(temp);
  394.         }
  395.         if (parity) {
  396.  
  397.         conol(", ");
  398.         switch (parity) {
  399.             case 'e': conol("even");  break;
  400.  
  401.             case 'o': conol("odd");   break;
  402.             case 's': conol("space"); break;
  403.             case 'm': conol("mark");  break;
  404.         }
  405.         conol(" parity");
  406.         }
  407.         if (seslog) {
  408.         conol(", logging to "); conol(sesfil);
  409.             }
  410.         conoll(""); return;
  411.  
  412.     case '?':            /* Help */
  413.         c = hconne(); continue;
  414.  
  415.     case '0':            /* Send a null */
  416.         c = '\0'; d = dopar(c); ttoc(d); return;
  417.  
  418.     case SP:            /* Space, ignore */
  419.         return;
  420.  
  421.     default:            /* Other */
  422.         conoc(BEL); return;     /* Invalid esc arg, beep */
  423.         }        
  424.     }
  425. }    
  426.  
  427.  
  428.  
  429.