home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / perkinelmeridris / pe7pho.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  14KB  |  539 lines

  1. /* pe7pho.c */
  2. /*
  3.  *  P h o n e   File Transfer Utility
  4.  *
  5.  * usage:
  6.  * phone -i -d -v -l -b -a -p -h -c
  7.  *
  8.  *  where   i=init modem <flag>, d=debug level <number>, v=verbose <flag>,
  9.  *            l=line <device>, b=baud rate <number>, a=answer <flag>,
  10.  *            p=phone number <string>, h=hang-up request <'a' or 'o'>,
  11.  *            c=direct connect <'a' or 'o'>
  12.  */
  13.  
  14. /*
  15.  *  Modification History:
  16.  *
  17.  *  June 85    - Init write. Dan L. Eisner, Perkin-Elmer Corp.
  18.  *
  19.  */
  20.  
  21. #include <std.h>        /* Standard IDRIS definitions */
  22. #include <sys.h>        /* Idris system subroutines */
  23. /*#include "sgtty.h"        /* Special TTY speed definations */
  24. #include "pe7tty.h"        /* Special TTY speed definations */
  25.  
  26. /* Symbol Definitions */
  27.  
  28. #define BUFSIZE 80        /* A buffer size for I/O */
  29.  
  30. #define MYTIME  10        /* Seconds after which I should be timed out */
  31.  
  32. #define TRUE    -1        /* Boolean constants */
  33. #define FALSE   0
  34.  
  35. /* Global Variables */
  36.  
  37. int
  38.     iflg {0},            /* Indicates to init the modem */
  39.     aflg {0},            /* Indicates modem mode */
  40.     vflg {0},            /* Indicates verbose mode */
  41.     hflg {0},            /* Indicates to hang up the phone */
  42.     cflg {0},            /* direct connection thru a modem flag */
  43.     timint {0},            /* This is the present time out interval */
  44.     debug {0};            /* indicates level of debugging output (0=none) */
  45.  
  46. char modem_data[BUFSIZE] {0};/* Temp buffer for modem command data */
  47.  
  48. FILE   ttyfd {0};        /* File descriptor of tty for I/O */
  49.  
  50. struct tty
  51.         savemode {0},    /* tty saved mode */
  52.         ttymode {0};    /* tty raw mode */
  53. /*
  54.  *  m a i n
  55.  *
  56.  *  Main routine - parse command and options, set up the
  57.  *  tty lines, and dispatch to the appropriate routine.
  58.  */
  59.  
  60. main(argc,argv)
  61. int argc;                /* Character pointers to and count of */
  62. char **argv;            /* command line arguments */
  63.  
  64. {
  65.     char *ttyname,        /* tty name for LINE argument */
  66.     *ph_num,            /* Phone number for PHONE argument */
  67.     result_code,        /* The code the modem answered with */
  68.     tmp[6];                /* Retry counter buffer */
  69.     int speed;            /* speed of assigned tty, */
  70.     int dial_count;        /* Number of times we have dialed the phone */
  71.     int answer_count;   /* The number of times we tried to answer phone */
  72.     int pflg;            /* A flag to set if there is a phone number */
  73.     int pdial;            /* Pulse dialing flag */
  74.  
  75.         /* Make sure there's a command line */
  76.     if (argc < 2)
  77.         Usage("phone -i -d# -v -l/dev/tty# -b<rate> -a -p<tel. no> -h -c\n");
  78.  
  79.     iflg = FALSE;
  80.     aflg = FALSE;
  81.     hflg = FALSE;
  82.     vflg = FALSE;
  83.     cflg = FALSE;        /* Turn off all parse flags */
  84.     ttyname = 0;        /* We did not get a line assignment (pointer) */
  85.     ph_num = NULL;        /* Set the phone number pointer to a null */
  86.     pflg = FALSE;        /* ... and the flag to FALSE */
  87.     speed = 0;            /* Preset the speed to no change */
  88.     debug = FALSE;        /* Turn off the debug mode */
  89.  
  90.     getflags(&argc,&argv, "i,a,v,h?,c?,l*,p*,b#,d#:F",
  91.     &iflg, &aflg, &vflg, &hflg, &cflg, &ttyname, &ph_num, &speed, &debug);
  92.  
  93.     /* Done parsing */
  94.  
  95.     if (debug > 0)
  96.         vflg = TRUE;        /* Force verbose during debug */
  97.  
  98.     pflg = (ph_num != 0);/* Set up a phone number flag */
  99.     if (!aflg && !pflg && !hflg && !cflg && !iflg)
  100.         Usage("We need to do something?");
  101.  
  102.     if ((aflg + pflg) > 1)
  103.         Usage("Dial and answer the phone?");
  104.  
  105.     if (cflg && (aflg || pflg))
  106.         Usage("Direct connect and dial at same time?");
  107.  
  108.     if (hflg != 0 && (aflg || pflg))
  109.         Usage("Hang-up after connecting?");
  110.  
  111.     if (cflg == 'a' || cflg == 'A')
  112.         aflg = TRUE; /* make it answer */
  113.  
  114.     if (cflg == 'o' || cflg == 'O')
  115.         pflg = TRUE;        /* force the dial routine to work */
  116.  
  117.     if (aflg || pflg)
  118.         iflg = TRUE;        /* force int of modem */
  119.  
  120.     if (ttyname == 0)        /* If LINE was not specified, we */
  121.         ttyname = "/dev/lnk0";/* operate with link tty */
  122.  
  123.     ttyfd = open(ttyname, UPDATE, 0);/* Open the tty line */
  124.     if (ttyfd < 0)
  125.         Usage("Cannot open %s.", ttyname);
  126.     
  127.     /* Put the proper tty into the correct mode */
  128.     egtty(ttyfd, &savemode);/* Save the inputed mode */
  129.     egtty(ttyfd,&ttymode);  /* set for changing the setup */
  130.  
  131.     ttymode.t_mode |= (M_ALL|M_RAW|MR_XON);
  132.     ttymode.t_mode &= ~(M_ECHO | M_2STOP);
  133.     ttymode.t_min = 128;
  134.     ttymode.t_time = 0;
  135.     timint = 0;
  136.  
  137.     if (speed)        /* User specified a speed? */
  138.     {
  139.         switch(speed)   /* Get internal system code */
  140.         {
  141.         case 110: speed = B110; ttymode.t_mode &= M_2STOP; break;
  142.         case 150: speed = B150; break;
  143.         case 300: speed = B300; break;
  144.         case 1200: speed = B1200; break;
  145.         case 2400: speed = B2400; break;
  146.         case 4800: speed = B4800; break;
  147.         case 9600: speed = B9600; break; 
  148.         default: Usage("Bad line speed.");
  149.         }
  150.         ttymode.t_ispeed = speed;
  151.         ttymode.t_ospeed = speed;
  152.     }
  153.  
  154.     estty(ttyfd, &ttymode);  /* Put asg'd tty in raw mode */
  155.  
  156.     if (debug)
  157.     {
  158.         printf("Main 1: A=%d, H=%d, D=%d, ", aflg, hflg, cflg);
  159.         printf("L=%s, P=%s\n", ttyname, ph_num);
  160.         printf("        Line speed to remote host is %d\n",speed);
  161.         printf("Main 2: Bits for ttyfd %x\n",ttymode.t_mode);
  162.     }
  163.  
  164.     /* All set up, now execute the command that was given. */
  165.  
  166.     if (iflg)        /* Init the modem */
  167.     {
  168.         timint = MYTIME / 2;
  169.         ttymode.t_time = timint * 10;
  170.         estty(ttyfd, &ttymode);  /* Put tty in short time mode */
  171.         if (vflg) printmsg("Initializing the modem");
  172.         if ((result_code = init_modem()) <= 0)
  173.             Usage("Can not initilize the modem, return = %d\n",result_code);
  174.     }
  175.     if (pflg)
  176.     {
  177.         timint = 0;
  178.         ttymode.t_time = 0;
  179.         estty(ttyfd, &ttymode);  /* Put tty in long time mode */
  180.   
  181.         /* If the first character of the phone number is a p then set
  182.             up pulse dialing. */
  183.         if (*ph_num == 'p' || *ph_num == 'P')
  184.         {
  185.             pdial = TRUE;
  186.             ph_num++;
  187.         }
  188.         else
  189.             pdial = FALSE;    /* Set pulse dialing to FALSE */
  190.         dial_count = 0;
  191.         if (vflg) printmsg("Dialing %s", ph_num);
  192.         do
  193.         {
  194.             if (dial_count++ >= 5)
  195.                 Usage("Dial count expired");
  196.             modem_write(pdial ? "ATPD" : "ATTD", FALSE);
  197.             if (!cflg)
  198.                 modem_write(ph_num,FALSE);
  199.             modem_write("\r",FALSE);
  200.             if(vflg)
  201.                 write(STDERR, &tmp, decode(&tmp, 3, "%2i\r", dial_count));
  202.         }
  203.         while ((result_code = get_result()) == '3');   /* keep dialing */
  204.         
  205.         if (result_code != '1' && result_code != '5')
  206.         {
  207.             init_modem();
  208.             Usage("    \007ERROR, BAD RESULT CODE: 0x%x\r",result_code);
  209.         }
  210.         
  211.         if (vflg)
  212.             printmsg("Connect at %s\n",
  213.                 result_code == '5' ? "1200 Baud" : "300 Baud");
  214.         sleep(2);            /* Wait for other side to be ready */
  215.         timint = MYTIME;
  216.         ttymode.t_time = timint * 10; /* Reset time out */
  217.         estty(ttyfd, &ttymode);
  218.  
  219.     }        /* End of pflg */
  220.     if (aflg)
  221.     {
  222.         answer_count = 0;
  223.         if (!cflg)            /* Direct mode is off? */
  224.         {
  225.             timint = 30;        /* set the time to 30 sec. */
  226.             ttymode.t_time = 50;/* Make the time out as big as I can */
  227.             estty(ttyfd, &ttymode);
  228.             if (vflg) printmsg("Waiting for ring");
  229.             do
  230.             {
  231.                 if (answer_count++ >= 10)
  232.                     Usage("Answer count expired.");
  233.                 if(vflg)
  234.                     write(STDERR, &tmp, decode(&tmp, 3, "%2i\r",
  235.                         answer_count));
  236.             }
  237.             /* wait for phone to ring (but count tries) */
  238.             while ((result_code = get_result()) != '2');
  239.             modem_write("ATS2=28A\r",FALSE);    /* Answer the phone */
  240.             result_code = get_result();
  241.         }
  242.         else    /* !cflg */
  243.         {
  244.             timint = 0;
  245.             ttymode.t_time = 0;    /* set time out */
  246.             estty(ttyfd, &ttymode);
  247.             if (vflg) printmsg("Waiting for connection");
  248.             do
  249.             {
  250.                 if (answer_count++ >= 5)
  251.                     Usage("Answer counter expired.");
  252.                 modem_write("ATS2=28A\r",FALSE); /* Answer the phone */
  253.                 if(vflg)
  254.                     write(STDERR, &tmp, decode(&tmp, 3, "%2i\r",
  255.                         answer_count));
  256.             }
  257.             while ((result_code = get_result()) == '3');
  258.  
  259.         }    /* end of else !cflg */
  260.         if (result_code != '1' && result_code != '5')
  261.             Usage("Modem failed to answer correctly.");
  262.         if (vflg)
  263.             printmsg("Answered at %s\n",
  264.                 result_code == '5' ? "1200 Baud" : "300 Baud");
  265.         timint = MYTIME;
  266.         ttymode.t_time = timint * 10;   /* Reset time out */
  267.         estty(ttyfd, &ttymode);  /* Put tty in time out mode */
  268.     }   /* end of aflg */
  269.     if (hflg)
  270.     {
  271.         timint = MYTIME / 5;
  272.         ttymode.t_time = timint * 10;    /* restore time out count */
  273.         estty(ttyfd, &ttymode);
  274.         if(vflg) printmsg("Hanging up");
  275.         hang_modem();    /* Hang up the phone */
  276.     }    /* end of else !hflg */
  277.  
  278.     estty(ttyfd, &savemode);
  279.     exit(YES);
  280. }
  281.  
  282. /*
  283.  * p r i n t m s g
  284.  *
  285.  * printmsg - like printf with "Phone: " preappended
  286.  */
  287. printmsg(fmt, a1, a2, a3, a4, a5)
  288. TEXT *fmt;
  289. {
  290.     char cp[BUFSIZE];
  291.     cpystr(&cp, "Phone: ", fmt, "\n", NULL);
  292.     printf(&cp, a1, a2, a3, a4, a5);
  293. }
  294.  
  295. /*
  296.  * U s a g e
  297.  *
  298.  * Print formatted message and the exit with a status of NO
  299.  */
  300. Usage(message, a1, a2, a3, a4, a5)
  301. char *message;
  302. {
  303.     char cp[BUFSIZE];
  304.  
  305.     cpystr(&cp, "Phone usage: ", message, "\n", NULL);
  306.     printf(&cp, a1, a2, a3, a4, a5);
  307.     if (ttyfd > 0)
  308.         estty(ttyfd, &savemode);    /* restore the tty */
  309.     exit(NO);
  310. }
  311.  
  312. /*
  313.  * p r i n t f
  314.  *
  315.  * Print formatted output. Convert from UNIX to IDRIS
  316.  */
  317. printf(msg, a1, a2, a3, a4, a5)
  318. char *msg;
  319. {
  320.     char t,
  321.     *cpp,
  322.     cp[BUFSIZE]; /* Line pointer for the reformatted string */
  323.  
  324.     cpp = cp;        /* Init the buffer pointer */
  325.  
  326.     while ((t = *cpp++ = *msg++) != NULL)
  327.         if (t == '%')
  328.             switch(t = *msg)
  329.             {
  330.             case 'd': *cpp++ = 'i';
  331.                 t = *msg++; /* Scrap character */
  332.                 break;
  333.             case 'c': *cpp++ = 'a';
  334.                 *cpp++ = 'c';
  335.                 t = *msg++; /* Scrap character */
  336.                 break;
  337.             case 'x': *cpp++ = 'h';
  338.                 *cpp++ = 'i';
  339.                 t = *msg++; /* Scrap character */
  340.                 break;
  341.             case 's': *cpp++ = 'p';
  342.                 t = *msg++; /* Scrap character */
  343.                 break;
  344.             case '\0': break;
  345.             default: *cpp++ = *msg++;
  346.             }
  347.     putfmt(&cp, a1, a2, a3, a4, a5);
  348. }
  349.  
  350. /*
  351.  * i n i t _ m o d e m
  352.  *
  353.  * Init the modem. first try to reset then if not successful then try to
  354.  *  escape the modem, and reset.
  355.  * The routine returns a result of '0' to '5' or a negative number for timeout
  356.  */
  357. char init_modem()
  358. {
  359.     int tries;
  360.     char tmp;
  361.  
  362.     if (debug) printf("Init_modem 1:\n");
  363.  
  364.     for (tries = 1; tries <= 4; tries++)
  365.     {
  366.         sleep(1);                /* Wait for a bit */
  367.         if (tries >= 2)
  368.         {
  369.             modem_write("\34\34\34",FALSE);
  370.             if ((tmp = get_result()) != '0')
  371.             {
  372.                 modem_write("\35\35\35",FALSE);
  373.                 if ((tmp = get_result()) != '0')
  374.                 {
  375.                     modem_write("+++",FALSE);
  376.                     tmp = get_result();
  377.                 }
  378.             }
  379.         }
  380.         modem_write("\rATZ\r", FALSE);
  381.         if ((tmp = get_result()) == '0') break;
  382.         if (debug) printf("Init_modem 2: tries = %d\n",tries);
  383.     }
  384.     if (tries > 4) return(tmp);
  385.  
  386.     sleep(2);    /* wait for a while while the modem resets */
  387.     modem_write("AT E0 F1 Q0 V1 X1 S0=0 S5=255 S2=29 \r",TRUE);
  388.     if (debug) printf("Init_modem exit\n");
  389.     return(get_result());
  390. }
  391.  
  392. /*
  393.  * h a n g _ m o d e m
  394.  *
  395.  * Hang up the modem. First escape to the command mode, then hang up the
  396.  * phone.
  397.  * The routine returns a result of '0' or a negative number for timeout
  398.  */
  399. char hang_modem()
  400. {
  401.     int tries;
  402.     char tmp;
  403.  
  404.     if (debug) printf("Hang_modem 1:\n");
  405.  
  406.     for (tries = 1; tries <= 4; tries++)
  407.     {
  408.         sleep(2);                /* Wait for a bit each time */
  409.         modem_write((hflg == 'a' || hflg == 'A') ?
  410.             "\34\34\34" : "\35\35\35", FALSE);
  411.         if ((tmp = get_result()) != '0')
  412.         {
  413.             modem_write("\34\34\34",FALSE);
  414.             if ((tmp = get_result()) != '0')
  415.             {
  416.                 modem_write("\35\35\35",FALSE);
  417.                 if ((tmp = get_result()) != '0')
  418.                 {
  419.                     modem_write("+++",FALSE);
  420.                     tmp = get_result();
  421.                 }
  422.             }
  423.         }
  424.         modem_write("ATH0\r", FALSE);
  425.         if ((tmp = get_result()) == '0') break;
  426.         if (debug) printf("Hang_modem 2: tries = %d\n",tries);
  427.     }
  428.     if (debug) printf("Hang_modem exit\n");
  429.     return(tmp);
  430. }
  431. /*
  432.  * g e t _ r e s u l t
  433.  *
  434.  * This routine finds out the result code from the modem.
  435.  */
  436. char get_result()
  437. {
  438.     int tmpx;    /* The status and goes here */
  439.     char result;
  440.     result = 0;    /* Reset the result flag */
  441.     while (result == 0)  /* do till something comes in that we recognize */ 
  442.     {
  443.         if ((tmpx = modem_read(&modem_data)) <= 0)
  444.             result = -1;
  445.         else if (modem_data[substr(&modem_data, "OK")])
  446.             result = '0';
  447.         else if (modem_data[substr(&modem_data, "CONNECT 1200")])
  448.             result = '5';
  449.         else if (modem_data[substr(&modem_data, "RING")])
  450.             result = '2';
  451.         else if (modem_data[substr(&modem_data, "NO CARRIER")])
  452.             result = '3';
  453.         else if (modem_data[substr(&modem_data, "ERROR")])
  454.             result = '4';
  455.         else if (modem_data[substr(&modem_data, "CONNECT")])
  456.             result = '1';
  457.         if (debug)
  458.             printf("Get_result 1: %c, %d, \"%s\"\n",result,tmpx,modem_data);
  459.     }   /* End of while loop */
  460.     if (debug)
  461.         printf("Get_result 2: %c, %d, \"%s\"\n",result,tmpx,modem_data);
  462.     return(result);
  463. }
  464. /*
  465.  * m o d e m _ w r i t e
  466.  *
  467.  * send a string to the modem. If eat is TRUE, eat a single echo per xmitted
  468.  * character. Does not account for echoed \n's after \r's. Current version
  469.  * turns off command echo anyway, so no difference. 
  470.  */
  471.  
  472. modem_write(s, eat)
  473. char *s;
  474. int eat;
  475. {
  476.     char t;
  477.     int tmpx;
  478.     tmpx = 1;
  479.     while (*s)
  480.     {
  481.         write(ttyfd, s++, 1);
  482.         if (eat)
  483.             if ((tmpx = ioread(&t)) <= 0) break;
  484.     }
  485.     return(tmpx);
  486. }
  487. /*
  488.  * m o d e m _ r e a d
  489.  *
  490.  * Modem read routine. This routine reads the returned control data from
  491.  *  The modem.
  492.  */
  493. modem_read(t)
  494. char *t;
  495. {
  496.     char chr;
  497.     BYTES point;
  498.     point = t;    /* Set pointer to start of the string */
  499.     while (TRUE)
  500.     {
  501.         if (ioread(t) <= 0) break; /* If an error or eof then exit */
  502.         if (*t == '\n')    /* What was the last character? */
  503.         {
  504.             *t++ = '\134'; *t++ = 'n';  /* Make the return into a \n */
  505.             break;    /* If it was an EOL then exit */
  506.         }
  507.         if ((chr = *t) < ' ')
  508.         {
  509.             *t++ = '\134'; *t = chr + '@'; /* Make control to alpha */
  510.         }
  511.         t++;            /* Bump the pointer */
  512.     }
  513.     *t = NULL;    /* Make sure the string ends with a null */
  514.     return(t - point);   /* Return a character counter */
  515. }
  516.  
  517. /*
  518.  *  i o r e a d
  519.  *
  520.  *  Read a character from the i/o channel
  521.  */
  522. ioread(t)
  523. char *t;
  524. {
  525. ULONG time_end,
  526.       time();
  527. int result;
  528.     if (timint > 0)
  529.     {
  530.         time_end = time() + timint;
  531.         while (time_end >= time())
  532.             if ((result = read(ttyfd, t, 1)) > 0) break;
  533.     }
  534.     else
  535.         result = read(ttyfd, t, 1);
  536.     return(result);
  537. }
  538. /* pe7pho.c End-of-file */
  539.