home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / MODEMS / MODEM2 / CMODEM13.C < prev    next >
C/C++ Source or Header  |  2000-06-30  |  14KB  |  566 lines

  1.  
  2.  
  3.  
  4. /*This program implements the Ward Christensen assembly language
  5.   program in C.  All of the original modes are available, and a
  6.   capture buffer was added to the terminal and computer modes.
  7.   The UNIX and PDP10 modes were added to facilitate sending files
  8.   to those systems.  Note that the original version of this program
  9.   was written for the D.C. Hayes modem board -  however, this
  10.   version is for the PMMI modem.
  11.  
  12.                                   original by Jack M. Wierda
  13.                                   modified by Roderick W. Hart
  14. */
  15. #include     <pmmi.h>
  16.  
  17. #define      FALSE  0
  18. #define      TRUE  1
  19. #define      NUL  0
  20. #define      SOH  1
  21. #define      CTRLB 2
  22. #define      CTRLC  3
  23. #define      EOT  4
  24. #define      ERRORMAX  5
  25. #define      RETRYMAX  5
  26. #define      CTRLE  5
  27. #define      ACK  6
  28. #define      TAB  9
  29. #define      LF  10
  30. #define      CR  13
  31. #define      CTRLQ  17
  32. #define      SPS 2750           /*loops per second*/
  33. #define      CTRLS  19
  34. #define      NAK  21
  35. #define      CTRLZ  26
  36. #define      SPACE  32
  37. #define      DELETE  127
  38. #define      TIMEOUT  -1
  39. #define      SECSIZ  0x80
  40. #define      DATAMASK 0x7f
  41. #define      BUFSIZ  0x7f80    /*maximum size, 0x8000 will not work with
  42.                   with BDS C, reduce buffer size as necessary
  43.                                   for smaller systems*/
  44.  
  45. char cntrlw0, cntrlw1, cntrlw2, cntrlw3;
  46. char hangup, option, option2, mode, baudrate, display, system;
  47. char asciiflg, showtrans, showrecv, view, dtrr;
  48. char buffer[BUFSIZ];
  49.  
  50. moready()
  51. {
  52.    return (inp(STATPORT) & TBMT) == (MAHI ? TBMT : 0);
  53.    }
  54. miready()
  55. {
  56.    return (inp(STATPORT) & DAV) == (MAHI ? DAV : 0);
  57.    }
  58. ctsready()
  59. {
  60.    return (inp(MODEMCP2) & CTS) == (CTSHI ? CTS : 0);
  61.    }
  62. sendline(data)
  63. char data;
  64. {
  65.   while(!MOREADY());
  66.   outp(DATAPORT,data);
  67.   if(showtrans)
  68.     { if(asciiflg)
  69.         if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR 
  70.             || data == TAB)
  71.           putchar(data);
  72.         else
  73.           printf("[%0x]",data);
  74.       if(option2 == 'H')
  75.         printf("[%0x]",data);
  76.     }
  77. }
  78.  
  79. readline(seconds)
  80. int seconds;
  81. {
  82.   char data;
  83.   seconds = seconds * SPS;
  84.   while (!MIREADY() && seconds--);
  85.   if(seconds < 0)
  86.     return(TIMEOUT);
  87.   data = inp(DATAPORT);
  88.   if(showrecv)
  89.     { if(asciiflg)
  90.         if(((data >= ' ') && (data <= 0x7f)) || data == LF || data == CR 
  91.             || data == TAB)
  92.           putchar(data);
  93.         else
  94.           printf("[%0x]",data);
  95.       if(option2 == 'H')
  96.         printf("<%0x>",data);
  97.     }
  98.   return(data);
  99. }
  100.  
  101. purgeline()
  102. {
  103.   while (MIREADY())
  104.     inp(DATAPORT);   /*PURGE THE RECEIVE REGISTER*/
  105. }
  106.  
  107. initializemodem()
  108. {
  109.   char cdflg;
  110.   cdflg = TRUE;
  111.   if((option == 'R') || (option == 'S'))
  112.     { cntrlw0 = ORIG + NB1 + NB2 + NP;
  113.       cntrlw3 = dtrr;
  114.     }
  115.   else
  116.     { cntrlw0 = ORIG + NB2 + EPS;
  117.       cntrlw3 = dtrr;
  118.     }
  119.    if(!CTSREADY())
  120.     { printf("Waiting for carrier\n");
  121.       cdflg = FALSE;
  122.     }
  123.    while(!CTSREADY() && !bios(2))
  124.     { outp(STATPORT,cntrlw0);
  125.       outp(MODEMCP2,cntrlw2);
  126.       outp(MODEMCP3,cntrlw3);
  127.       outp(DATAPORT,cntrlw1);
  128.     }
  129.   if(CTSREADY() && !cdflg)
  130.     printf("Carrier detected\n");
  131.       outp(STATPORT, (cntrlw0 & 0xfe));
  132.   purgeline();
  133. }
  134.  
  135. sendstr(str)
  136. char *str;
  137. {
  138.   while(*str)
  139.     if(option == 'U')
  140.       sendline(tolower(*str++));
  141.     else
  142.       sendline(*str++);
  143. }
  144.  
  145. termcomp()
  146. {
  147.   char bflag, kbdata, moddata;
  148.   int fd;
  149.   int bufctr;
  150.   bflag = FALSE;
  151.   bufctr = 0;
  152.   initializemodem();
  153.   while((CTSREADY()) && (kbdata !=CTRLE))
  154.     { if(bios(2))
  155.         switch(kbdata = bios(3))
  156.           { case CTRLB:
  157.               bflag = ~bflag;
  158.               if(bflag)
  159.                 printf("Capture initiated");
  160.               else
  161.                 printf("Capture terminated");
  162.               printf(", %u bytes free\n",BUFSIZ - bufctr);
  163.               break;
  164.             case CTRLE:
  165.               break;
  166.             default:
  167.               if(option == 'C')
  168.                 { putchar(kbdata);
  169.                   if(bflag && (bufctr < BUFSIZ))
  170.                     buffer[bufctr++] = kbdata;
  171.                 }
  172.               outp(DATAPORT,kbdata);
  173.               break;
  174.           }
  175.       if(MIREADY())
  176.         { moddata = inp(DATAPORT);
  177.           if(option == 'C')
  178.             outp(DATAPORT,moddata);
  179.           if(bflag && (bufctr < BUFSIZ))
  180.             buffer[bufctr++] = moddata;
  181.           else if(bflag)
  182.             printf("Buffer overflow\n");
  183.           putchar(moddata);
  184.         }
  185.     }
  186.   if(bufctr)
  187.     { buffer[bufctr] = CTRLZ;
  188.       fd = creat("cmodem.tmp");
  189.       if(fd == -1)
  190.         { printf("Cannot create cmodem.tmp\n");
  191.           exit();
  192.         }
  193.       write(fd,buffer,1 + (bufctr/SECSIZ));
  194.       close(fd);
  195.     }
  196. }
  197.  
  198. putbuffer(buffer,sectors)
  199. char *buffer;
  200. int sectors;
  201. {
  202.   char ch, moddata; 
  203.   unsigned  k;
  204.   ch = 0;
  205.   k = 0;
  206.   while((ch != CTRLZ) && (k < sectors * SECSIZ) && (CTSREADY()))
  207.         { k = k+1;
  208.           if((ch = *buffer++) == LF)        /*don't send LF's*/
  209.             putchar(LF);
  210.           else
  211.             if(ch != CTRLZ || option != 'U') /*don't send CTRLZ to UNIX*/
  212.               sendline(ch);
  213.           if(!(k & 0xff))                   /*let other end catch-up*/ 
  214.              while(readline(1) != TIMEOUT);
  215.         }
  216. }
  217.  
  218. pdp10(file)
  219. char *file;
  220. {
  221.   char sectors;
  222.   int fd;
  223.   showrecv = FALSE;
  224.   asciiflg = showtrans = TRUE;
  225.   fd = open(file,0);
  226.   if(fd == -1)
  227.     { printf("Cannot open %s\n",file);
  228.       exit();
  229.     }
  230.   initializemodem();
  231.   if(option == 'P')
  232.     { sendstr("\nR PIP\n");
  233.       while((readline(1) != '*') && !bios(2));
  234.       if(*(++file) != ':')
  235.         sendstr(--file);
  236.       else
  237.         sendstr(++file);
  238.       sendstr("=TTY:\n");
  239.     }
  240.   else
  241.     { sendstr("\ncat > ");
  242.       if(*(++file) != ':')
  243.         sendstr(--file);
  244.       else
  245.         sendstr(++file);
  246.       sendstr("\n");
  247.     }
  248.   while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) == BUFSIZ/SECSIZ)
  249.     putbuffer(buffer,sectors);
  250.   if(sectors)
  251.     putbuffer(buffer,sectors);
  252.   close(fd);
  253.   while(readline(1) != TIMEOUT);
  254.   if(option == 'P')
  255.     sendline(CTRLC);
  256.   else
  257.     { sendline(CR);
  258.       sendline(LF);
  259.       sendline(EOT);
  260.     }
  261.   while(readline(10) != TIMEOUT);
  262.   sendline(CR);
  263.   sendline(LF);
  264. }
  265.  
  266. readfile(file)
  267. char *file;
  268. { int j, firstchar, sectnum, sectcurr, sectcomp, errors;
  269.   int checksum;
  270.   int errorflag, fd;
  271.   int bufctr;
  272.  
  273.   if(view)
  274.     { showrecv = TRUE;
  275.       showtrans = FALSE;
  276.     }
  277.   option2 = 'A';
  278.   fd = creat(file);
  279.   if(fd == -1)
  280.     { printf("Cannot create %s\n",file);
  281.       exit();
  282.     }
  283.   sectnum = 0;
  284.   errors = 0;
  285.   bufctr = 0;
  286.   initializemodem();
  287.   sendline(NAK);
  288.   do
  289.     { errorflag = FALSE;
  290.       do
  291.         firstchar = readline(6);
  292.       while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);
  293.       if(firstchar == TIMEOUT)
  294.         { errorflag = TRUE;
  295.           printf("SOH timeout\n");
  296.         }
  297.       if(firstchar == SOH)
  298.         { sectcurr = readline(1);
  299.           sectcomp = readline(1);
  300.           if((sectcurr + sectcomp) == 255)
  301.             { if(sectcurr == sectnum + 1)
  302.                 { checksum = 0;
  303.                   if(option2 == 'A')
  304.                     asciiflg = TRUE;
  305.                   for(j = bufctr;j < (bufctr + SECSIZ);j++)
  306.                     { buffer[j] = readline(1);
  307.                       checksum = (checksum + buffer[j]) & 0xff;
  308.                     }
  309.                   asciiflg = FALSE;
  310.                   if(checksum == readline(1))
  311.                     { errors = 0;
  312.                       sectnum = sectcurr;
  313.                       bufctr = bufctr + SECSIZ;
  314.                       if(bufctr == BUFSIZ)
  315.                         { bufctr = 0;
  316.                           write(fd,buffer,BUFSIZ/SECSIZ);
  317.                         }
  318.                       if(!showrecv)
  319.                         printf("Received sector %d\n",sectcurr);
  320.                       sendline(ACK);
  321.                     }
  322.                   else
  323.                     { printf("Checksum error, expected <%0x>\n",checksum);
  324.                       errorflag = TRUE;
  325.                     }
  326.                 }
  327.               else
  328.                 if(sectcurr == sectnum)
  329.                   { do;
  330.                     while(readline(1) != TIMEOUT);
  331.                     printf("Received duplicate sector %d\n", sectcurr);
  332.                     sendline(ACK);
  333.                   }
  334.                 else
  335.                   { printf("Synchronization error\n");
  336.                     errorflag = TRUE;
  337.                   }
  338.               }
  339.             else
  340.               { printf("Sector number error\n");
  341.                 errorflag = TRUE;
  342.               }
  343.           }
  344.        if(errorflag == TRUE)
  345.          { errors++;
  346.            printf("Error %d\n",errors);
  347.            while(readline(1) != TIMEOUT);
  348.            sendline(NAK);
  349.          }
  350.      }
  351.   while(firstchar != EOT && errors != ERRORMAX);
  352.   if((firstchar == EOT) && (errors < ERRORMAX))
  353.     { sendline(ACK);
  354.       write(fd,buffer,1 + (bufctr/SECSIZ));
  355.       close(fd);
  356.       printf("Transfer complete\n");
  357.     }
  358.   else
  359.     printf("Aborting\n");
  360. }
  361.  
  362. sendfile(file)
  363. char *file;
  364. {
  365.   int j, sectnum, sectors, attempts;
  366.   int checksum;
  367.   int bufctr, fd;
  368.  
  369.   if(view)
  370.     { showrecv = FALSE;
  371.       showtrans = TRUE;
  372.     }
  373.   option2 = 'A';
  374.   fd = open(file,0);
  375.   if(fd == -1)
  376.     { printf("Cannot open %s\n",file);
  377.       exit();
  378.     }
  379.   initializemodem();
  380.   attempts = 0;
  381.   sectnum = 1;
  382.   while((sectors = read(fd,buffer,BUFSIZ/SECSIZ)) && (attempts != RETRYMAX))
  383.     { if(sectors == -1)
  384.         printf("\nFile read error\n");
  385.       else
  386.         { bufctr = 0;
  387.           do
  388.             { attempts = 0;
  389.               do
  390.                 { if(!showtrans)
  391.                     printf("\nSending sector %d\n",sectnum);
  392.                   sendline(SOH);
  393.                   sendline(sectnum);
  394.                   sendline(-sectnum-1);
  395.                   checksum = 0;
  396.                   if(option2 == 'A')
  397.                     asciiflg = TRUE;
  398.                   for(j = bufctr;j < (bufctr + SECSIZ);j++)
  399.                     { sendline(buffer[j]);
  400.                       checksum = (checksum + buffer[j]) & 0xff;
  401.                     }
  402.                   asciiflg = FALSE;
  403.                   sendline(checksum);
  404.                   purgeline();
  405.                   attempts++;
  406.                 }
  407.               while((readline(10) != ACK) && (attempts != RETRYMAX));
  408.               bufctr = bufctr + SECSIZ;
  409.               sectnum++;
  410.               sectors--;
  411.             }
  412.           while((sectors != 0) && (attempts != RETRYMAX));
  413.         }
  414.     }
  415.       if(attempts == RETRYMAX)
  416.         printf("\nNo ACK on sector, aborting\n");
  417.       else
  418.         { attempts = 0;
  419.           do
  420.             { sendline(EOT);
  421.               purgeline();
  422.               attempts++;
  423.             }
  424.           while((readline(10) != ACK) && (attempts != RETRYMAX));
  425.           if(attempts == RETRYMAX)
  426.             printf("\nNo ACK on EOT, aborting\n");
  427.           else
  428.             printf("\nTransfer complete\n");
  429.         } 
  430.   close(fd);
  431. }
  432.  
  433. ckfile(argc) int argc;
  434. { if(!argc)
  435.     { printf("File required\n");
  436.       exit();
  437.     }
  438. }
  439.  
  440. main(argc,argv)
  441. int argc;
  442. char **argv;
  443. { char *s;
  444.   printf("Cmodem (Pmmi) ver 1.3  13-Apr-81\n");
  445.   printf("      mod. by Rod Hart\n");
  446.  cntrlw2 = 0;
  447.   asciiflg = hangup = showrecv = showtrans = view = FALSE;
  448.   if(**++argv != '-')
  449.     { printf("Command line format: cmodem -options file1 file2 ... file14\n");
  450.       printf("Available options are:\n");
  451.       printf("\ta: answer          t: terminal\n");
  452.       printf("\tc: computer        u: UNIX\n");
  453.       printf("\th: auto-hangup     v: view data\n");
  454.       printf("\to: originate       1: 110 baud\n");
  455.       printf("\tp: PDP10           3: 300 baud\n");
  456.       printf("\tr: receive file    4: 450 baud\n");
  457.       printf("\ts: send file       6: 600 baud\n");
  458.       printf("The p, r, s, and u options require one or more files.\n");
  459.       printf("Ctrl-B initiates and terminates data capture in file\n");
  460.       printf("cmodem.tmp in the terminal and computer modes.\n");
  461.       printf("Ctrl-E is used to initiate file transfers in the UNIX and\n");
  462.       printf("PDP10 modes. In the terminal mode Ctrl-E escapes to the\n");
  463.       printf("hangup question or CP/M.\n");
  464.       printf("Any character escapes the no carrier condition.\n");
  465.       exit();
  466.     }
  467.   --argv;
  468.   while(--argc && **++argv == '-')
  469.     for(s = *argv+1;*s;s++)
  470.       switch(*s)
  471.         { case 'C':
  472.           case 'P':
  473.           case 'R':
  474.           case 'S':
  475.           case 'T':
  476.           case 'U':
  477.             option = *s;
  478.             break;
  479.           case 'A':
  480.             cntrlw0 = cntrlw0 + ANS;
  481.             break;
  482.           case 'H':
  483.             hangup = TRUE;
  484.             break;
  485.           case 'V':
  486.             view = TRUE;
  487.             break;
  488.           case 'O':
  489.             cntrlw0 = cntrlw0 + ORIG;
  490.             break;
  491.           case '1':
  492.             cntrlw2 = BR110;
  493.             dtrr = UND300;
  494.             break;
  495.           case '3':
  496.             cntrlw2 =  BR300;
  497.             dtrr =  UND300;
  498.             break;
  499.           case '4':
  500.             cntrlw2 =  BR450;
  501.             dtrr =  OVR300;
  502.             break;
  503.           case '6':
  504.             cntrlw2 =  BR600;
  505.             dtrr =  OVR300;
  506.             break;
  507.           default:
  508.             printf("Unimplemented option %c\n\n",*s);
  509.             exit();
  510.             break;
  511.         }
  512.       switch(option)
  513.         { case 'C':
  514.           case 'T': 
  515.             termcomp();
  516.             break;
  517.           case 'P': 
  518.           case 'U':
  519.             ckfile(argc);
  520.             termcomp();
  521.             while(argc--)
  522.               { printf("\nSending %s\n",*argv);
  523.                 pdp10(*argv++);
  524.               }
  525.             termcomp();
  526.             break;
  527.           case 'R': 
  528.             ckfile(argc);
  529.             while(argc--)
  530.               { printf("\nReceiving %s\n",*argv);
  531.                 readfile(*argv++);
  532.               }
  533.             break;
  534.           case 'S': 
  535.             ckfile(argc);
  536.             while(argc--)
  537.               { printf("\nSending %s\n",*argv);
  538.                 sendfile(*argv++);
  539.               }
  540.             break;
  541.         }
  542.       if(hangup)
  543.         outp(MODEMCP3,0x00);
  544.       else
  545.         { do
  546.             { printf("\nHangup : Y(es), N(o) ? ");
  547.               hangup = tolower(getchar());
  548.               printf("\n");
  549.             }
  550.           while((hangup != 'y') && (hangup != 'n'));
  551.           if(hangup == 'y')
  552.             outp(MODEMCP3,0x00);
  553.         }
  554. }
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.