home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_48.arc / PPXFER.ARC / PPXFER.C < prev    next >
Text File  |  1989-05-16  |  6KB  |  213 lines

  1. /* Support code from Micro Cornucopia Magazine Issue #48
  2.  
  3. Micro Cornucopia
  4. PO Box 223
  5. Bend, OR 97709 */
  6.  
  7. #include <io.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <fcntl.h>
  11. #include <sys/stat.h>
  12. #include <stdlib.h>
  13. #include <errno.h>
  14. #include <dir.h>
  15. #include <time.h>    /* to calculate transfer speeds */
  16. #include "ppxfer.h"  /* header file containing appropriate definitions */
  17.  
  18. dbyte base_plus_two;  /* global so output value at BASE+2 doesn't accidentally
  19.             get changed */
  20. #define RAISE_HANDSHAKE (outportb(BASE+2, base_plus_two &= ~(1 << 3)))
  21. #define LOWER_HANDSHAKE (outportb(BASE+2, base_plus_two |= (1 << 3)))
  22.  
  23. #define TESTKEY  if (kbhit()) break
  24.  
  25. /* Prints a byte in binary (for testing): */
  26. void print_binary(dbyte c) {
  27.   int i = 7;
  28.   do printf("%c", c & (1 << i) ? '1' : '0'); while(i--);
  29. }
  30.  
  31. /* Set the channel to the "idle" state: */
  32. void idle(void) {
  33.   outportb(BASE,0xff);  /* all lines high */
  34.   /* initialize so everything's an input (handshake is high): */
  35.   outportb(BASE+2, (base_plus_two = 0x04));
  36. }
  37.  
  38. dbyte receive_byte(void) {
  39.   dbyte data;
  40.   while( ! (inportb(BASE+2) & (1<<3)))
  41.     ;
  42.   data = (inportb(BASE+1) & 0xf8) | (inportb(BASE+2) & 0x07);
  43.   outportb(BASE, 0xfe);  /* send BYTE RECD signal */
  44.   data ^= 0x83;  /* flip "inverted" bits */
  45.   while( (inportb(BASE+2) & (1<<3)))
  46.     ;
  47.   outportb(BASE, 0xff);  /* de-assert BYTE RECD signal */
  48.   return data;
  49. }
  50.  
  51. void send_byte( dbyte data) {
  52.   outportb(BASE, data);
  53.   LOWER_HANDSHAKE;
  54.   while( ! (inportb(BASE+2) & 1)) {
  55.     if (inportb(BASE+2) & 2) {
  56.       puts("aborted by receiver");
  57.       exit(1);
  58.     }
  59.     TESTKEY;
  60.   }
  61.   RAISE_HANDSHAKE;
  62.   while ( inportb(BASE + 2) & 1) {
  63.     if (inportb(BASE+2) & 2) { puts("aborted"); exit(1); }
  64.     TESTKEY;
  65.   }
  66. }
  67.  
  68. void send_string( char * string) {
  69.   while(*string) {
  70.     send_byte(*string);
  71.     string++;
  72.   }
  73. }
  74.  
  75. void usage(char * msg) {
  76.   puts("\nusage: ppxfer -s file1.ext ...");
  77.   puts("    to send files through the parallel port using the special");
  78.   puts("    cable configuration, (the list of files can be any length;");
  79.   puts("    wildcards may be used in the file name) or:");
  80.   puts("ppxfer -sh file1.ext ...");
  81.   puts("    to send files and leave the receiver on hold so other");
  82.   puts("    files may be sent, or:");
  83.   puts("ppxfer -r");
  84.   puts("    to receive files.");
  85.   puts(msg);
  86.   exit(1);
  87. }
  88.  
  89. void send_file(char * unambiguous_name) {
  90.   int i, infile;
  91.   unsigned long filesize, readsize;
  92.   char buf[30];
  93.   dbyte filebuf[BUFSIZE];
  94.   long secs_start, secs_end;  /* for timing */
  95.  
  96.   if ((infile = open(unambiguous_name,O_RDONLY | O_BINARY )) < 0 ) {
  97.     puts("cannot open file to send:");
  98.     puts(unambiguous_name);
  99.     exit(1);
  100.   }
  101.   filesize = lseek(infile, 0L, 2);  /* find file size */
  102.   lseek(infile, 0L, 0);  /* reset file pointer to beginning */
  103.   ultoa(filesize,buf,10);
  104.   idle();
  105.   send_byte(ATTN);  /* send an escape */
  106.   send_string("filename"); send_byte(LDELIMIT);
  107.   send_string(unambiguous_name); send_byte(RDELIMIT);
  108.   send_byte(LDELIMIT);
  109.   send_string(buf); send_byte(RDELIMIT);
  110.   printf("sending %-15s  size: %s bytes:  ", unambiguous_name, buf);
  111. #ifdef TIME
  112.   time(&secs_start);
  113.   printf("starting time: %d\n", secs_start);
  114. #endif TIME
  115.   while((readsize = read(infile, filebuf, BUFSIZE)) > 0 )
  116. #ifdef MASM
  117.     send_block(filebuf, readsize);
  118. #else MASM  /* if you don't have MASM, you'll have to do it the slow way: */
  119.   for (i = 0; i < readsize; i++)
  120.     send_byte(filebuf[i]);
  121. #endif MASM
  122.   close(infile);
  123. #ifdef TIME
  124.   time(&secs_end);
  125.   printf("ending time: %d\n", secs_end);
  126.   printf("%f Kbytes/sec\n", (filesize/1000)/(secs_end - secs_start));
  127. #endif TIME
  128. }
  129.  
  130. void receive_files(void) {
  131.   char c;
  132.   int i,j, outfile;
  133.   unsigned long incr, filesize, bytecount, readsize;
  134.   char buf[30], filename[30];
  135.   dbyte filebuf[BUFSIZE];
  136.  
  137.   idle();
  138.   while(1) {
  139.     while ( receive_byte() != ATTN )
  140.       if (kbhit()) if (getch() == 27) exit(1);
  141.      /* hunt for an ESCAPE from the port or the keyboard */
  142.     for (i=0; (c = receive_byte()) != LDELIMIT; )
  143.       buf[i++] = c;
  144.     buf[i] = 0;  /* end of control string */
  145.     if (strcmp(buf,"end of transaction") == 0) {
  146.       puts("end of transaction");
  147.       exit(0);
  148.     }
  149.     if (strcmp(buf,"filename") == 0) {
  150.       for (i=0; (c = receive_byte()) != RDELIMIT; )
  151.         filename[i++] = c;
  152.       filename[i] = 0;
  153.       for (i=0; (c = receive_byte()) != LDELIMIT; )
  154.         ; /* throw away characters until left delimiter */
  155.       for (i=0; (c = receive_byte()) != RDELIMIT; )
  156.         buf[i++] = c; /* store characters until right delimiter */
  157.       buf[i] = 0;
  158.       filesize = atol(buf);
  159.       printf("receiving %-15s  size: %s bytes\n",filename, buf);
  160.       if ((outfile = open(filename,
  161.          O_WRONLY | O_BINARY | O_CREAT, S_IREAD|S_IWRITE)) < 0 ) {
  162.         puts("cannot open output file");
  163.         outportb(BASE,0xfd);  /* set "abort" line */
  164.         switch(errno) {
  165.           case ENOENT: puts("path or file name not found"); break;
  166.           case EMFILE: puts ("too many open files"); break;
  167.           case EACCES: puts ("permission denied"); break;
  168.           case EINVACC: puts("invalid access code");
  169.         }
  170.         exit(1);
  171.       }
  172.       for (incr = (signed)(filesize - BUFSIZE) > 0 ?
  173.         BUFSIZE : filesize, bytecount = 0;
  174.         bytecount < filesize;
  175.         bytecount += incr,
  176.         incr = filesize - bytecount > BUFSIZE ? BUFSIZE
  177.         : filesize - bytecount ) {
  178.           receive_block(filebuf,incr);
  179.           write(outfile, filebuf, incr);
  180.       }
  181.       close(outfile);
  182.     }
  183.   }
  184. }
  185.  
  186. void main(int argc, char * argv[]) {
  187.   struct ffblk file_block;
  188.   int i, done;
  189.  
  190.   if (argv[1][0] != '-' ||
  191.     (argv[1][1] != 's' && argv[1][1] != 'r')) usage("use '-s' or '-r'");
  192.  
  193.   /* receive files: */
  194.   if (argv[1][1] == 'r')
  195.     receive_files();
  196.  
  197.   /* send files using wildcards: */
  198.   if (argv[1][1] == 's' ) {
  199.     if (argc < 3) usage("not enough arguments");
  200.     for(i = 2; i < argc; i++) {
  201.       done = findfirst(argv[i],&file_block,0);
  202.       while (!done) {
  203.         send_file(file_block.ff_name);
  204.         done = findnext(&file_block);
  205.       }
  206.     }
  207.     if (argv[1][2] == 'h')
  208.       { puts("receiver ready for more files");  exit(0); }
  209.     send_byte(ATTN);
  210.     send_string("end of transaction"); send_byte(LDELIMIT);
  211.   }
  212. }
  213.