home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MODEM / XMODM11.ZIP / XMODM11.C
Encoding:
C/C++ Source or Header  |  1988-07-28  |  12.4 KB  |  458 lines

  1. /*This program implements the Ward Christenson assembly language
  2.   program in C.  All of the original modes are available, and a
  3.   hide mode is added for restriction of file availability. A logger
  4.   has been added, to keep a record of which files are most
  5.   popular with BBS callers. Also, a local CRT display of errors
  6.   and progress is implemented. This program as written is for the
  7.   PMMI modem board, but may be changed for the D.C.Hayes via the
  8.   proper equates. It requires CP/M Vers. 2.x to operate. Derived
  9.   from CMODEM13.C
  10.  
  11.                                   original by Jack M. Wierda
  12.                                   modified by Roderick W. Hart
  13.                   modified by William D. Earnest
  14. */
  15. #include     <bdscio.h>
  16. #include     <pmmi.h>
  17.  
  18. #define      SOH 1
  19. #define      EOT 4
  20. #define      ACK 6
  21. #define      TAB 9
  22. #define      CPUCLK 4
  23. #define      ERRORMAX 10
  24. #define      RETRYMAX 10
  25. #define      LF 10
  26. #define      CR 13
  27. #define      SPS 1500           /*loops per second */
  28. #define      NAK 21
  29. #define      CTRLZ 26
  30. #define      DELETE 127
  31. #define      TIMEOUT -1
  32. #define      LRL 16      /* logger record lgth */
  33. #define      RPB 8       /* logger rcrds per sector */
  34. #define      SECSIZ 0x80
  35. #define      TBFSIZ 0x2000    /*moderate size, 0x8000 will not work with
  36.                   with BDS C, reduce buffer size as necessary
  37.                                   for smaller systems*/
  38.  
  39. char option,buffer[TBFSIZ],fcb[36],crtm[24];
  40.  
  41. moready()
  42. { return (inp(STATPORT) & TBMT) == (MAHI ? TBMT : 0);
  43. }
  44.  
  45. miready()
  46. { return (inp(STATPORT) & DAV) == (MAHI ? DAV : 0);
  47. }
  48.  
  49. ctsready()
  50. { int lpc,seccnt;
  51.     for(lpc=0; lpc < 25; lpc++)
  52.         { seccnt = SPS * CPUCLK;
  53.             while((inp(MODEMCP2) & CTS) == (CTSHI ? 0 : CTS) && seccnt--);
  54.             if(seccnt >= 0)
  55.                 return;
  56.         }
  57.     exit();
  58. }
  59.  
  60. crtmsg(msg)
  61. char *msg;
  62. { while (*msg)
  63.         { while((inp(CSTAT) & COMASK) == (CAHI ? 0 : COMASK));
  64.             outp(CDATA,*msg);
  65.             msg++;
  66.         }
  67. }
  68.  
  69. shocrt(sec,try,tot)
  70. int sec,try,tot;
  71. { sprintf(crtm,"\015Blk %04d Try %1d Err %03d",sec,try,tot);
  72.     crtmsg(crtm);
  73. }
  74.  
  75. sendline(data)
  76. char data;
  77. { ctsready();
  78.     while(!MOREADY());
  79.     outp(DATAPORT,data);
  80. }
  81.  
  82. readline(seconds)
  83. int seconds;
  84. { char data;
  85.     int lpc,seccnt;
  86.     for (lpc = 0; lpc < CPUCLK; lpc++)
  87.         { seccnt = seconds * SPS;
  88.           ctsready();
  89.           while (!MIREADY() && seccnt--);
  90.           if(seccnt >= 0)
  91.               { data = inp(DATAPORT);
  92.                 return(data);
  93.               }
  94.         }
  95.     return(TIMEOUT);
  96. }
  97.  
  98. purgeline()
  99. { while (MIREADY())
  100.       inp(DATAPORT);     /*PURGE THE RECEIVE REGISTER*/
  101.   ctsready();
  102. }
  103.  
  104. readfile(file)
  105. char *file;
  106. { int j, firstchar, sectnum, sectcurr, sectcomp, errors;
  107.   int toterr,checksum;
  108.   int errorflag, fd;
  109.   int bufctr;
  110.  
  111.   fd = creat(file);
  112.   if(fd == -1)
  113.       { printf("Cannot create %s\n",file);
  114.         exit();
  115.       }
  116.   else
  117.       printf("\nReady to receive %s\n",file);
  118.   sectnum = 0;
  119.   errors = 0;
  120.   toterr = 0;
  121.   bufctr = 0;
  122.   purgeline();
  123.   shocrt(0,0,0);
  124.   do
  125.       { errorflag = FALSE;
  126.         do
  127.             firstchar = readline(10);
  128.         while(firstchar != SOH && firstchar != EOT && firstchar != TIMEOUT);
  129.  
  130.         if(firstchar == TIMEOUT)
  131.             errorflag = TRUE;
  132.         if(firstchar == SOH)
  133.             { sectcurr = readline(1);
  134.               sectcomp = readline(1);
  135.               if((sectcurr + sectcomp) == 255)
  136.                   { if(sectcurr == sectnum + 1)
  137.                         { checksum = 0;
  138.                           for(j = bufctr;j < (bufctr + SECSIZ);j++)
  139.                               { buffer[j] = readline(1);
  140.                                 checksum = (checksum + buffer[j]) & 0xff;
  141.                               }
  142.                           if(checksum == readline(1))
  143.                               { errors = 0;
  144.                                 sectnum = sectcurr;
  145.                                 bufctr = bufctr + SECSIZ;
  146.                                 if(bufctr == TBFSIZ)
  147.                                     { bufctr = 0;
  148.                                       write(fd,buffer,TBFSIZ/SECSIZ);
  149.                                     }
  150.                                 shocrt(sectnum,errors,toterr);
  151.                                 sendline(ACK);
  152.                               }
  153.                           else
  154.                               errorflag = TRUE;
  155.                         }
  156.                     else
  157.                         if(sectcurr == sectnum)
  158.                             { do;
  159.                               while(readline(1) != TIMEOUT);
  160.                               sendline(ACK);
  161.                             }
  162.                         else
  163.                             errorflag = TRUE;
  164.                   }
  165.               else
  166.                   errorflag = TRUE;
  167.             }
  168.         if(errorflag == TRUE)
  169.             { errors++;
  170.               if(sectnum)
  171.                   toterr++;
  172.               while(readline(1) != TIMEOUT);
  173.               shocrt(sectnum,errors,toterr);
  174.               sendline(NAK);
  175.             }
  176.       }
  177.   while(firstchar != EOT && errors != ERRORMAX);
  178.  
  179.   if((firstchar == EOT) && (errors < ERRORMAX))
  180.       { sendline(ACK);
  181.         write(fd,buffer,(bufctr+SECSIZ-1)/SECSIZ);
  182.         close(fd);
  183.       }
  184.   else
  185.       printf("Aborting\n");
  186. }
  187.  
  188. sendfile(file)
  189. char *file;
  190. { char *npnt;
  191.   int j, sectnum, sectors, attempts;
  192.   int toterr,checksum;
  193.   int bufctr, fd;
  194.  
  195.   fd = open(file,0);
  196.   if(fd == -1)
  197.       { printf("\n++File not found++\n");
  198.         exit();
  199.       }
  200.   else
  201.       { npnt = fcbaddr(fd);
  202.         if(npnt[1] > 127 || npnt[2] > 127)
  203.             { printf("\nFile %s not for distribution, Sorry.\n",file);
  204.               exit();
  205.             }
  206.         else
  207.             { attempts = rcfsiz(fd);
  208.               printf("\nFile %s open, ",file);
  209.               printf("size %d (%04xH) sectors.\n",attempts,attempts);
  210.               printf("Ready to send, awaiting NAK.\n");
  211.             }
  212.       }
  213.   purgeline();
  214.   attempts=0;
  215.   toterr = 0;
  216.   shocrt(0,0,0);
  217.   while((readline(10) != NAK) && (attempts != 8))
  218.       { attempts++;
  219.         shocrt(0,attempts,0);
  220.       }
  221.   if (attempts == 8)
  222.       { printf("\nTimed out awaiting initial NAK\n");
  223.         exit();
  224.       }
  225.   attempts = 0;
  226.   sectnum = 1;
  227.   while((sectors = read(fd,buffer,TBFSIZ/SECSIZ)) && (attempts != RETRYMAX))
  228.       { if(sectors == -1)
  229.             { printf("\nFile read error.\n");
  230.               break;
  231.             }
  232.         else
  233.             { bufctr = 0;
  234.               do
  235.                   { attempts = 0;
  236.                     do
  237.                         { shocrt(sectnum,attempts,toterr);
  238.                           sendline(SOH);
  239.                           sendline(sectnum);
  240.                           sendline(-sectnum-1);
  241.                           checksum = 0;
  242.                           for(j = bufctr;j < (bufctr + SECSIZ);j++)
  243.                               { sendline(buffer[j]);
  244.                                 checksum = (checksum + buffer[j]) & 0xff;
  245.                               }
  246.                           sendline(checksum);
  247.                           purgeline();
  248.                           attempts++;
  249.                           toterr++;
  250.                         }
  251.                     while((readline(10) != ACK) && (attempts != RETRYMAX));
  252.                     bufctr = bufctr + SECSIZ;
  253.                     sectnum++;
  254.                     sectors--;
  255.                     toterr--;
  256.                   }
  257.               while((sectors != 0) && (attempts != RETRYMAX));
  258.             }
  259.       }
  260.         if(attempts == RETRYMAX)
  261.             printf("\nNo ACK on sector, aborting\n");
  262.         else
  263.             { attempts = 0;
  264.               do
  265.                   { sendline(EOT);
  266.                     purgeline();
  267.                     attempts++;
  268.                   }
  269.               while((readline(10) != ACK) && (attempts != RETRYMAX));
  270.               if(attempts == RETRYMAX)
  271.                   printf("\nNo ACK on EOT, aborting\n");
  272.             } 
  273.   close(fd);
  274. }
  275.  
  276. docfile(file)
  277. char *file;
  278. { int fd,rcsz,rch;
  279.   fd = open(file,0);
  280.   if(fd == -1)
  281.       { printf("\n++File %s not found++\n,file");
  282.         exit();
  283.       }
  284.   else
  285.       { rcsz=rcfsiz(fd);
  286.         rch = (rcsz * 14) / 3;
  287.         printf("\nFile %s is ",file);
  288.         printf("%d (%04xH) sectors long.\n",rcsz,rcsz);
  289.         printf("At 300 baud, it would take about ");
  290.         printf("%d minutes, %d seconds to send.\n",rch / 60,rch % 60);
  291.       }
  292. }
  293.  
  294. int filfnd(file)
  295. char *file;
  296. { if(setfcb(fcb,file))
  297.       return FALSE;
  298.   if(bdos(17,fcb) != 255)
  299.       return TRUE;
  300.   else
  301.       return FALSE;
  302. }
  303.  
  304. char matchr(st,ch)
  305. char *st,ch;
  306. { int i;
  307.   for(i=0; st[i]; i++)
  308.       { if(st[i] == ch)
  309.             return(i);
  310.       }
  311.   return(0);
  312. }
  313.  
  314. ckfile(argc,argv) int argc;
  315. char **argv;
  316. { char *s,l;
  317.   if(argc < 3)
  318.       { printf("File name required\n");
  319.         exit();
  320.       }
  321.  
  322.   if(option == 'H')
  323.       { l = matchr(*argv,'.');
  324.         if(((l+3) > strlen(*argv)) || (!l))
  325.             { printf("\nMust have full .typ to Hide\n");
  326.               exit();
  327.             }
  328.       }
  329.  
  330.   for(s=*argv; *s; s++)
  331.       { if((*s == '?') || (*s == '*'))
  332.             { printf("\nNo 'Wild Card' characters allowed\n");
  333.               exit();
  334.             }
  335.       }
  336.  
  337.   for(s=*argv; *s; s++)
  338.       { if((*s == '.') && ((option == 'R') || (option == 'H')))
  339.             { if(s[1] == 'C' && s[2] == 'O' && s[3] == 'M')
  340.                   { printf("\nCan't accept a .COM file\n");
  341.                     exit();
  342.                   }
  343.               if(option == 'H')
  344.                   s[2] = s[2] | 0x80;
  345.             }
  346.       }
  347. }
  348.  
  349. char bbcd(val)
  350. char val;
  351. { return(((val / 10) << 4) + (val % 10));
  352. }
  353.  
  354. logfil(file)
  355. char *file;
  356. { int fd,rnum,bnum,savusr;
  357.   char *i,*lrec,lbuf[128],*lnam;
  358.   lnam = "A:\330\315ODEM.L\317G"; /* f1 & f2 flags, $sys */
  359.   savusr = bdos(32,-1);
  360.   bdos(32,0);
  361.   fd = open(lnam,2);
  362.   if(fd == -1)
  363.       { fd = creat(lnam);
  364.         if(fd == -1)
  365.             return;
  366.         else
  367.             { setmem(lbuf,16,0x20);
  368.               setmem(lbuf+16,112,CTRLZ);
  369.               sprintf(lbuf,"%d",0);
  370.             }
  371.       }
  372.   else
  373.       read(fd,lbuf,1);
  374.   rnum = atoi(lbuf)+1;
  375.   sprintf(lbuf,"%d",rnum);
  376.   seek(fd,0,0);
  377.   write(fd,lbuf,1);
  378.   bnum = rnum / RPB;
  379.   rnum = (rnum % RPB) * LRL;
  380.   seek(fd,bnum,0);
  381.   if(rnum == 0)
  382.       setmem(lbuf,128,CTRLZ);
  383.   else
  384.       read(fd,lbuf,1);
  385.   if(peek(0xe802) == 0xc3)
  386.       call(0xe802,0,0,0,0); /* r.t.c. put data in hi mem */
  387.   lrec = lbuf+rnum;
  388.   movmem(0xf406,lrec-4+LRL,4); /* time/date data from hi mem */
  389.   for(i = lrec-4+LRL; i < lrec+LRL; i++)
  390.       *i = bbcd(*i);
  391.   movmem(0x6c,lrec,12);
  392.   if(peek(0x6c) == 0)
  393.       *lrec = peek(4) + 1;
  394.   *lrec = *lrec | (peek(4) & 0xf0);
  395.   if((option == 'R') || (option == 'H'))
  396.       *lrec = *lrec | 0x80;
  397.   seek(fd,bnum,0);
  398.   write(fd,lbuf,1);
  399.   close(fd);
  400.   bdos(32,savusr); /* restore orig user nr */
  401. }
  402.  
  403. main(argc,argv)
  404. int argc;
  405. char **argv;
  406. { char *s;
  407.   printf("XMODEM (PMMI/BDS-C) ver 1.1    9-Jul-81\n");
  408.   s=*++argv;
  409.   ++argv;
  410.   switch(s[0])
  411.       { case 'R':
  412.         case 'S':
  413.         case 'H':
  414.         case 'Q':
  415.             option = s[0];
  416.             break;
  417.  
  418.         default:
  419.             printf("Command format: XMODEM option filename.typ\n");
  420.             printf("Available options are:\n");
  421.             printf("\tS: Send file     R: Receive file\n");
  422.             printf("\tH: Hide file     Q: Query file size\n");
  423.             exit();
  424.             break;
  425.       }
  426.  
  427.   switch(option)
  428.       { case 'R': 
  429.         case 'H':
  430.             ckfile(argc,argv);
  431.             if (filfnd(*argv))
  432.                 { printf("\nFile %s exists, pick another name.\n",*argv);
  433.                   exit();
  434.                 }
  435.             else
  436.                 { logfil(*argv);
  437.                   readfile(*argv);
  438.                 }
  439.             break;
  440.  
  441.         case 'S': 
  442.             ckfile(argc,argv);
  443.             if (filfnd(*argv))
  444.                 { logfil(*argv);
  445.                   sendfile(*argv);
  446.                 }
  447.             else
  448.                 { printf("\n++File %s not found++\n",*argv);
  449.                   exit();
  450.                 }
  451.             break;
  452.  
  453.         case 'Q':
  454.             docfile(*argv);
  455.             break;
  456.       }
  457. }
  458.