home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 8 / boot-disc-1997-04.iso / PDA_Soft / Psion / comms / p3nfs / nfsd / mp_xmit.c < prev    next >
C/C++ Source or Header  |  1996-05-16  |  7KB  |  368 lines

  1. /*
  2.  * Protocol:
  3.  *
  4.  * new: PREFIX byte + old:
  5.  * old:
  6.  *
  7.  * Host sends command length (1 byte) + command
  8.  * A command consists of:
  9.  *  bcpl filename + 0 byte + 
  10.  *  command specific data (0-6 bytes) + command type (1 byte)
  11.  * Command specific data:
  12.  * - CREATE/SETATTR: attributes (NYI)
  13.  * - RENAME: strlen of the second bcpl string
  14.  * - READ/WRITE: 4 byte offset, 2 byte length
  15.  * - GETVERS: filename[0] == 'C' and return > 1 then crc is used: 
  16.  *     - READ/WRITE: after the data 2 byte crc follows.
  17.  *
  18.  * Answer:
  19.  * new: PREFIX byte + old:
  20.  * old:
  21.  * - status of operation (0 for success)
  22.  * - Thereafter, if return is 0 and op is
  23.  *   - GETATTR, a 12 byte attribute structure is sent
  24.  *   - READ,    the data is sent (+crc).
  25.  *   - READDIR, a list of cstrings are sent, the last is of length 0
  26.  *   - GETDEVS, a list of (cstring + 14 bytes), the last ...
  27.  *   - WRITE, when crc is used, if crc is ok byte 0 is returned.
  28.  *
  29.  *
  30.  * In short:
  31.  *
  32.  * Command:
  33.  * - PREFIX 0x80, omitted if old protocol is used
  34.  * - command length
  35.  * - namelen
  36.  * - name
  37.  * - 0x00
  38.  * - request data (0-6 bytes)
  39.  * - request type
  40.  * 
  41.  *
  42.  * Answer:
  43.  * - PREFIX 0x80, omitted if old protocol is used
  44.  * - status (0 == OK)
  45.  * - data
  46.  *
  47.  */
  48.  
  49. #include <stdio.h>
  50. #include <sys/time.h>
  51. #include <sys/types.h>
  52. #ifdef _IBMR2
  53. # include <sys/select.h>
  54. #endif
  55. #include <termios.h>    /* for tcdrain() */
  56. #ifdef __svr4__
  57. #include <poll.h>
  58. #include <unistd.h>
  59. #include <string.h>
  60. #endif
  61. #include "nfs_prot.h"
  62. #include "mp.h"
  63. #include "config.h"
  64.  
  65. /* Since the psion is little endian, we have to do some conversion */
  66. /* Note: this should work for little endian hosts too */
  67.  
  68. #include <sys/errno.h>
  69. extern int errno;
  70. extern char *sys_errlist[];
  71.  
  72. void
  73. short2pstr(l, s)
  74.   unsigned int l;
  75.   unsigned char *s;
  76. {
  77.   s[0] = l & 0xff;
  78.   s[1] = (l & 0xff00) >> 8;
  79. }
  80.  
  81. void
  82. long2pstr(l, s)
  83.   unsigned int l;
  84.   unsigned char *s;
  85. {
  86.   s[0] = l & 0xff;
  87.   s[1] = (l & 0xff00) >> 8;
  88.   s[2] = (l & 0xff0000) >> 16;
  89.   s[3] = (l & 0xff000000) >> 24;
  90. }
  91.  
  92. unsigned int
  93. pstr2long(s)
  94.   unsigned char *s;
  95. {
  96.   int l = s[0];
  97.  
  98.   l |= s[1] <<  8; l |= s[2] << 16;
  99.   return l | (s[3] << 24);
  100. }
  101.  
  102.  
  103. int
  104. senddata(p, len)
  105.   char *p;
  106.   int len;
  107. {
  108.   int ret;
  109.   int lerr;
  110.  
  111.   if(debug) printf("\t-> psion\n");
  112.   psion_alive = fd_is_still_alive(psionfd,1);
  113.   if(!psion_alive)
  114.     {
  115.       if(debug) printf("Senddata: Not alive...\n");
  116.       return EOF;
  117.     }
  118.  
  119.   lerr = 0;
  120.   if(debug > 1) printf("\tSending: %#x, %d\n", (unsigned int)p, len);
  121.   while((ret = write(psionfd, p, len)) < len)
  122.     {
  123.       if(debug > 1)
  124.     fprintf(stderr, "\t\twrite(%d, %#x, %d) = %d\n",
  125.             psionfd, (unsigned int)p, len, ret);
  126.       if(ret > 0)
  127.     {
  128.       p += ret;
  129.       len -= ret;
  130.       lerr = 0;
  131.       continue;
  132.     }
  133.       if(ret < 0 && errno != EAGAIN)
  134.         {
  135.       perror("p3nfsd: Write");
  136.       return 1;
  137.     }
  138.  
  139.       lerr++;
  140.       if(lerr > 1)
  141.     {
  142.       if(debug)
  143.         fprintf(stderr, "\twrite=%d after flush/select\n", ret);
  144.       return 1;
  145.     }
  146.  
  147. #ifdef NO_WRITE_SELECT
  148.  
  149.       if(debug > 1)
  150.     fprintf(stderr, "\t\tdraining serial line\n");
  151.       if(tcdrain(psionfd))
  152.     perror("p3nfsd: tcdrain");
  153.  
  154. #else
  155.  
  156.       {
  157.     fd_set writefd;
  158.     struct timeval to;
  159.  
  160.     FD_ZERO(&writefd); FD_SET(psionfd, &writefd);
  161.     to.tv_sec = 2; to.tv_usec = 0; 
  162.     if((ret = select(psionfd+1, 0, &writefd, 0, &to)) <= 0)
  163.       {
  164.         if(debug)
  165.           fprintf(stderr, "p3nfsd: writeselect returned %d\n", ret);
  166.         return 1; 
  167.       }
  168.       }
  169.  
  170. #endif
  171.     }
  172.   if(debug > 1)
  173.     fprintf(stderr, "\t\twrite(%d, %#x, %d) = %d\n", psionfd, (unsigned int)p, len, ret);
  174.  
  175. #if !defined(linux)
  176.   /*
  177.    * tcdrain is broken on my linux version, strace reports 
  178.    * ioctl(3, TCSBRK, 0x1) = 0
  179.    */
  180. #endif
  181.   if(tcdrain(psionfd))
  182.     perror("p3nfsd: tcdrain");
  183.   return 0;
  184. }
  185.  
  186. static int
  187. getbyte()
  188. {
  189.   static unsigned char readbuf[256];
  190.   static int idx = 0, len = 0;
  191.   int err;
  192.  
  193.   if(idx == len)
  194.     {
  195.       for(;;)
  196.         {
  197. #ifdef __svr4__
  198.           struct pollfd readfd;
  199.  
  200.       errno = 0;
  201.       readfd.fd = psionfd;
  202.       readfd.events = POLLIN;
  203.       err = poll(&readfd, 1, 2000);
  204. #else
  205.           fd_set readfd;
  206.           struct timeval to;
  207.  
  208.       errno = 0;
  209.       to.tv_sec = 2; to.tv_usec = 0; 
  210.       FD_ZERO(&readfd); FD_SET(psionfd, &readfd);
  211.       err = select(psionfd+1, &readfd, 0, 0, &to);
  212. #endif
  213.       if (err <= 0)
  214.         {
  215.           if(errno == EINTR)
  216.             continue;
  217.           fprintf(stderr, "p3nfsd: select: %s\n",
  218.                   err < 0 ? sys_errlist[errno] : "timeout" );
  219.           return EOF;
  220.         }
  221.       break;
  222.     }
  223.  
  224.       idx = 0;
  225.       if(debug > 1) { printf("\t\tFilling read buffer..."); fflush(stdout); }
  226.       len = read(psionfd, readbuf, sizeof(readbuf));
  227.       if(debug > 1) printf("got %d bytes\n", len);
  228.       if(debug > 2) 
  229.         {
  230.       int i;
  231.  
  232.       for(i = 0; i < len; i++)
  233.         {
  234.           printf("%02x ", readbuf[i]);
  235.           if((i & 15) == 15)
  236.             printf("\n");
  237.         }
  238.       printf("\n");
  239.     }
  240.       if(len <= 0)
  241.         {
  242.       perror("p3nfsd: read"); len = 0;
  243.       return EOF;
  244.     }
  245.     }
  246.   return readbuf[idx++];
  247. }
  248.  
  249. int
  250. sendcmd(cmd, fname, rest, restlen)
  251.   char *fname, *rest;
  252.   int cmd, restlen;
  253. {
  254.   int l;
  255.   unsigned char mbuf[255], *str;
  256.  
  257.   if(old_nfsc)
  258.     str = mbuf;
  259.   else
  260.     {
  261.       str = mbuf+1;
  262.       mbuf[0] = PREFIX;
  263.     }
  264.  
  265.   str[1] = l = strlen(fname);
  266.   if(l + restlen + 4 > 254)
  267.     {
  268.       printf("Warning, length too large (%d)\n", l);
  269.       return 1;
  270.     }
  271.  
  272.   bcopy(fname, str+2, l+1);    /* include trailing \0 */
  273.   l += 3;
  274.   if(restlen)
  275.     {
  276.       bcopy(rest, str+l, restlen);
  277.       l += restlen;
  278.     }
  279.   str[l++] = cmd;
  280.   *str = l-1;
  281.  
  282.   if(debug > 1)
  283.     printf("\tSendcmd %d ('%s'+%d) %d bytes\n", cmd, fname, restlen, l);
  284.   return senddata((char *)mbuf, l + (old_nfsc ? 0 : 1));
  285. }
  286.  
  287. int
  288. getcount(str, num)
  289.   unsigned char *str; int num;
  290. {
  291.   int c;
  292.  
  293.   if(debug > 1) {printf("\tGoing to read %d bytes...",num);fflush(stdout);}
  294.   while(num-- > 0)
  295.     if((c = getbyte()) == EOF)
  296.       {
  297.     if(debug) printf("Bad connection to psion... (%d)\n", c);
  298.     return -53;
  299.       }
  300.     else
  301.       *str++ = c;
  302.   if(debug > 1) printf("\tRead ok\n");
  303.   return 0;
  304. }
  305.  
  306. int
  307. getstr(str)
  308.   unsigned char *str;
  309. {
  310.   int c;
  311.   unsigned char *s = str;
  312.  
  313.   if(debug > 1) {printf("\tGoing to read string...");fflush(stdout);}
  314.   for(;;)
  315.     {
  316.       if((c = getbyte()) == EOF)
  317.         {
  318.       if(debug) printf("Bad connection to psion... received EOF\n");
  319.       return 1;
  320.     }
  321.       *s++ = c;
  322.       if(c == 0)
  323.         {
  324.       if(debug > 1) printf(" got string (%s)\n", str);
  325.       return 0;
  326.     }
  327.     }
  328. }
  329.  
  330. /* Old protocol: 1 byte, new Protocol 2 bytes */
  331. int
  332. getanswer()
  333. {
  334.   int i;
  335.  
  336.   i = getbyte();
  337.   if(debug > 1) printf("Answer:(1) %#x\n", i);
  338.   if(old_nfsc)
  339.     return i;
  340.  
  341.   while(i != EOF)
  342.     {
  343.       if(i == PREFIX)
  344.         {
  345.       i = getbyte();
  346.       if(debug > 1) printf("Answer:(1) %#x\n", i);
  347.       break;
  348.     }
  349.       shell_feed(i); /* this byte *has to be* input for our shell */
  350.       i = getbyte();
  351.       if(debug > 1) printf("Answer:(3) %#x\n", i);
  352.     }
  353.   return i;
  354. }
  355.  
  356. int
  357. sendop(cmd, fname, rest, restlen)
  358.   char *fname, *rest;
  359.   int cmd, restlen;
  360. {
  361.   int i = EOF;
  362.  
  363.   if((i = sendcmd(cmd, fname, rest, restlen)) == 0)
  364.     i = getanswer();
  365.   if(debug > 1) printf("\tReceived: (op %d) %d\n", cmd, i);
  366.   return i;
  367. }
  368.