home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / stefanb_src / private_projects / fax / sendfax2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-06  |  6.0 KB  |  280 lines

  1. #include "serio.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <clib/dos_protos.h>
  6.  
  7. static struct ReadArgs *rda;
  8. static struct SerialStream *ss;
  9. static char Template[]="DEVICE/K,UNIT/K/N,BAUD/K/N,RETRIES/K/N,NUMBER/K,FILES/M/A";
  10. static struct {
  11.                char *device;
  12.                long *unit;
  13.                long *baud;
  14.                long *retries;
  15.                char *number;
  16.                char **files;
  17.               } def={"serial.device",NULL,NULL,NULL,NULL,NULL};
  18. #define BUFLEN 1024
  19. static UBYTE buffer[BUFLEN];
  20. static ULONG GlobalReturnCode;
  21. static BOOL notend;
  22. static BOOL notendofsession;
  23.  
  24. /* Read one reply line from modem */
  25. static void ReadLine(void *buf)
  26. {
  27.  char c='\0',*cp=buf;
  28.  
  29.  /* Read until EOL is reached */
  30.  while (c!='\n')
  31.   {
  32.    if (ReadSerialSynch(ss,&c,1)==0) break;
  33.    *cp++=c;
  34.   }
  35.  
  36.  /* Terminate string */
  37.  *cp='\0';
  38. }
  39.  
  40. /* Read and analyse modem reply */
  41. /* Possible normal replies */
  42. #define REPLY_OK          0
  43. #define REPLY_CONNECT     1
  44. #define REPLY_NO_CARRIER  3
  45. #define REPLY_ERROR       4
  46. #define REPLY_NO_DIALTONE 6
  47. /* Possible FAX Class II replies */
  48. #define REPLY_FHNG        10
  49.  
  50. static ULONG ReadModemReply(void)
  51. {
  52.  ULONG rc;
  53.  
  54.  while (TRUE)
  55.   {
  56.    /* Read one line */
  57.    ReadLine(buffer);
  58.    printf("%s",buffer);
  59.  
  60.    /* Skip empty lines */
  61.    if (strlen(buffer)==2) continue;
  62.  
  63.    /* Check for normal replies */
  64.    if (!strncmp(buffer,"OK",2))
  65.     {
  66.      rc=REPLY_OK;
  67.      break;
  68.     }
  69.    if (!strncmp(buffer,"CONNECT",7))
  70.     {
  71.      rc=REPLY_CONNECT;
  72.      break;
  73.     }
  74.    if (!strncmp(buffer,"NO CARRIER",10))
  75.     {
  76.      rc=REPLY_NO_CARRIER;
  77.      break;
  78.     }
  79.    if (!strncmp(buffer,"ERROR",5))
  80.     {
  81.      rc=REPLY_ERROR;
  82.      break;
  83.     }
  84.    if (!strncmp(buffer,"NO DIALTONE",11))
  85.     {
  86.      rc=REPLY_NO_DIALTONE;
  87.      break;
  88.     }
  89.  
  90.    /* Check for FAX Class II responses */
  91.    if (!strncmp(buffer,"+FHNG:",6))
  92.     {
  93.      rc=REPLY_FHNG;
  94.      GlobalReturnCode=atol(buffer+6);
  95.      break;
  96.     }
  97.  
  98.    /* Everything else is skipped */
  99.   }
  100.  
  101.  return(rc);
  102. }
  103.  
  104. /* Send a FAX page */
  105. static void SendFAXPage(FILE *fh)
  106. {
  107.  /* Wait until modem sent a XON */
  108.  {
  109.   char c='\0';
  110.   while (c!='\x11') ReadSerialSynch(ss,&c,1);
  111.  }
  112.  
  113.  /* Send FAX data */
  114.  while (!feof(fh))
  115.   {
  116.    ULONG len;
  117.    char *cp=buffer;
  118.  
  119.    /* Read data from file */
  120.    len=fread(buffer,1,BUFLEN,fh);
  121.  
  122.    /* Send buffer */
  123.    while (len--)
  124.     {
  125.      /* Write one byte */
  126.      WriteSerialSynch(ss,cp,1);
  127.  
  128.      /* Special DLE processing. DLE --> DLE DLE */
  129.      if (*cp=='\x10') WriteSerialSynch(ss,cp,1);
  130.  
  131.      /* Next byte */
  132.      cp++;
  133.     }
  134.  
  135.    /* Flow control */
  136.    if (QuerySerial(ss) && ((len = ss->ss_Unread)>0))
  137.     {
  138.      char c='\0';
  139.  
  140.      /* Read until XOFF */
  141.      while ((len--) && (c!='\x13')) ReadSerialSynch(ss,&c,1);
  142.  
  143.      /* Read until XON (will be skipped if no XOFF found!) */
  144.      while ((len--) && (c!='\x11')) ReadSerialSynch(ss,&c,1);
  145.     }
  146.   }
  147.  
  148.  /* End of FAX data, send DLE ETX */
  149.  WriteSerialSynch(ss,"\x10\x03",2);
  150. }
  151.  
  152. /* FAX session main loop */
  153. static void DoFAXSession(char **files)
  154. {
  155.  /* Repeat until end of session */
  156.  notendofsession=TRUE;
  157.  while (notendofsession)
  158.   {
  159.    struct FILE *fh;
  160.  
  161.    /* Open FAX file */
  162.    if (fh=fopen(*files,"r"))
  163.     {
  164.      /* Signal modem: "Ready to send phase C data!" */
  165.      WriteSerialSynch(ss,"AT+FDT\r",7);
  166.  
  167.      /* Got a CONNECT? */
  168.      switch(ReadModemReply())
  169.       {
  170.        case REPLY_CONNECT:    /* Yes. Send next page */
  171.                               puts("sending page");
  172.                               SendFAXPage(fh);
  173.                               puts("page send");
  174.                               ReadModemReply();
  175.                               puts("read reply");
  176.                               break;
  177.  
  178.        case REPLY_NO_CARRIER: /* No. Something has gone wrong */
  179.        case REPLY_ERROR:
  180.        case REPLY_FHNG:       notendofsession=FALSE;
  181.                               break;
  182.       }
  183.  
  184.      /* Close FAX file */
  185.      fclose(fh);
  186.     }
  187.    else printf("Couldn't open %s!\n",*files);
  188.  
  189.    /* Additional pages to send? */
  190.    if (notendofsession)
  191.     {
  192.      WriteSerialSynch(ss,"AT+FET=",7);
  193.      if (*++files)
  194.       WriteSerialSynch(ss,"0\r",2); /* Yes. */
  195.      else
  196.       WriteSerialSynch(ss,"2\r",2); /* No. End of document */
  197.  
  198.      /* Read reply */
  199.      if (ReadModemReply()!=REPLY_OK)
  200.       notendofsession=FALSE;
  201.     }
  202.   }
  203. }
  204.  
  205. /* CTRL-C shut down routine */
  206. static int Shutdown(void)
  207. {
  208.  notend=FALSE;
  209.  return(0);
  210. }
  211.  
  212. int main(int argc, char *argv[])
  213. {
  214.  int (*oldbreak)();
  215.  ULONG Unit,Baud,Retries;
  216.  
  217.  /* Read command line parameters */
  218.  if (!(rda=ReadArgs(Template,(LONG *) &def,NULL)))
  219.   {
  220.    PrintFault(IoErr(),argv[0]);
  221.    exit(20);
  222.   }
  223.  Unit=(def.unit)?(*def.unit):0;
  224.  Baud=(def.baud)?(*def.baud):19200;
  225.  Retries=(def.retries)?(*def.retries):5;
  226.  
  227.  /* Install CTRL-C shut down routine */
  228.  GlobalReturnCode=20;
  229.  notend=TRUE;
  230.  oldbreak=onbreak(Shutdown);
  231.  printf("'%s' %ld (%ldbps)\n",def.device,Unit,Baud);
  232.  
  233.  if (ss=CreateSerialStream(def.device,Unit,
  234.                            SERF_SHARED|SERF_7WIRE|SERF_RAD_BOOGIE))
  235.   {
  236.    if (SetSerialParamsTags(ss,SIO_Baud,Baud,TAG_DONE))
  237.     while (notend && Retries)
  238.      {
  239.       /* Init modem */
  240.       WriteSerialSynch(ss,"AT+fclass=2+fbor=0\r",19);
  241.       ReadModemReply();
  242.       WriteSerialSynch(ss,"AT+flid=+49-241-505705\r",23);
  243.       ReadModemReply();
  244.       WriteSerialSynch(ss,"AT+fdcc=0,5,0,2,0\r",18);
  245.       ReadModemReply();
  246.  
  247.       /* Dial number */
  248.       if (def.number)
  249.        {
  250.         WriteSerialSynch(ss,"ATDP",4);
  251.         WriteSerialSynch(ss,def.number,strlen(def.number));
  252.         WriteSerialSynch(ss,"\r",1);
  253.        }
  254.       else WriteSerialSynch(ss,"ATD\r",4);
  255.  
  256.       /* Got a connect? */
  257.       switch (ReadModemReply())
  258.        {
  259.         case REPLY_OK:DoFAXSession(def.files);
  260.                       Retries=0;
  261.                       break;
  262.         case REPLY_NO_DIALTONE:continue;
  263.         default:Retries--;
  264.        }
  265.      }
  266.    else puts("Couldn't set parameters!");
  267.  
  268.    DeleteSerialStream(ss);
  269.   }
  270.  else puts("Couldn't open stream!");
  271.  
  272.  /* Free command line parameters */
  273.  FreeArgs(rda);
  274.  
  275.  /* Leave program */
  276.  onbreak(oldbreak);
  277.  return(GlobalReturnCode);
  278. }
  279.  
  280.