home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / me34src.zip / me3 / comserver / movedata.c < prev   
C/C++ Source or Header  |  1995-01-14  |  7KB  |  282 lines

  1. /* movedata.c : move data between clients and servers.
  2.  */
  3.  
  4. /* Craig Durland    Public Domain
  5.  *   Distributed "as is", without warranties of any kind, but comments,
  6.  *     suggestions and bug reports are welcome.
  7.  */
  8.  
  9. /* ******************************************************************** */
  10. /* **************************** move data ***************************** */
  11. /* ******************************************************************** */
  12.  
  13. #ifdef __STDC__
  14.  
  15. #ifdef __hpux            /* for ANSI C on HP-UX */
  16. #define _HPUX_SOURCE
  17. #endif  /* __hpux */
  18.  
  19. #endif    /*  __STDC__ */
  20.  
  21. #include <stdio.h>
  22. #include <const.h>
  23. #include "comserver.h"
  24.  
  25. #include <errno.h>
  26.  
  27. #ifdef __STDC__
  28.  
  29. #include <stdarg.h>
  30. #define VA_START va_start
  31.  
  32. #else    /* __STDC__ */
  33.  
  34. #include <varargs.h>
  35. #define VA_START(a,b) va_start(a)
  36.  
  37. #endif
  38.  
  39.    /* Packet format:
  40.     *   <magic number><packet length><packet type><bytes>
  41.     *   offset:  0       1             2           3
  42.     */
  43. /*VARARGS3*/
  44. #ifdef __STDC__
  45. int CSbuild_packet(CSPacket *packet, int packet_type, char *format, ...)
  46. #else
  47. int CSbuild_packet(packet, packet_type, format, va_alist)
  48.   CSPacket *packet; int packet_type; char *format; va_dcl
  49. #endif
  50. {
  51.   char c, *ptr, *pak_ptr, *buf;
  52.   int n, size;
  53.   va_list ap;
  54.  
  55.   VA_START(ap,format);
  56.  
  57.   buf = packet->buf;
  58.  
  59.   buf[0] = CS_MAGIC;
  60.  
  61.   pak_ptr = buf + 2;
  62.  
  63.   *pak_ptr++ = (char)packet_type;
  64.  
  65.   size = 1;        /* type */
  66.   while (c = *format++)
  67.   {
  68.     switch (c)
  69.     {
  70.       case 'n':        /* number:  sizeof(int) bytes */
  71.     n = va_arg(ap,int);
  72.     memcpy(pak_ptr, (char *)&n, sizeof(int));
  73.     pak_ptr += sizeof(int); size += sizeof(int);
  74.     break;
  75.       case 's':        /* string: <text><trailing \0> */
  76.     ptr = va_arg(ap,char *);
  77.     strcpy(pak_ptr, ptr);
  78.     n = strlen(ptr);
  79.     pak_ptr += (n + 1); size += (n + 1);
  80.     break;
  81.     }
  82.   }
  83.  
  84.   buf[1] = (char)size;
  85.   packet->size = size + 2;    /* magic # and len */
  86.   packet->start = 0;
  87.  
  88.   va_end(ap);
  89.  
  90.   return TRUE;
  91. }
  92.  
  93. /*VARARGS2*/
  94. #ifdef __STDC__
  95. static void dig_out(CSPacket *packet, char *format, ...)
  96. #else
  97. static void dig_out(packet, format, va_alist)
  98.   CSPacket *packet; char *format; va_dcl
  99. #endif
  100. {
  101.   char c, *buf;
  102.   int n, *xp;
  103.   va_list ap;
  104.  
  105.   VA_START(ap,format);
  106.  
  107.   buf = &packet->buf[packet->start];
  108.  
  109.   n = 0;
  110.   while (c = *format++)
  111.   {
  112.     switch (c)
  113.     {
  114.       case 'b':        /* byte:  1 byte int */
  115.     xp = va_arg(ap,int *);
  116.     *xp = (int)buf[0];
  117.     buf += 1; n += 1;
  118.     break;
  119.       case 'n':        /* number:  sizeof(int) bytes */
  120.     xp = va_arg(ap,int *);
  121.     memcpy(xp, buf, sizeof(int));
  122.     buf += sizeof(int); n += sizeof(int);
  123.     break;
  124.       case 's':        /* string: <text><trailing \0> */
  125.       {
  126.     char **ptr;
  127.  
  128.     ptr = va_arg(ap,char **);
  129.     *ptr = buf;
  130.     /* string is last thing in a packet, don't need to inc pak_ptr */
  131.     break;
  132.       }
  133.     }
  134.   }
  135.  
  136.   packet->start += n;
  137.  
  138.   va_end(ap);
  139. }
  140.  
  141.     /* 
  142.      * Returns:
  143.      *   -1 : error
  144.      *    0 : couldn't write all of packet
  145.      *    1 : wrote all of packet
  146.      *    2 : didn't write anything
  147.      * Notes:
  148.      *   The compute server sets the socket to be nonblocking but most
  149.      *     clients expect it to block.  I think this will work in both cases
  150.      *     but since writes to the server should always suceed, I don't
  151.      *     think I have to worry about it.
  152.      *   The packet better have a nonzero size.  This is to make O_NDELAY
  153.      *     work.  I like O_NONBLOCK lots better.
  154.      */
  155. CSwrite_packet(packet, fd) CSPacket *packet; int fd;
  156. {
  157.   int n, size;
  158.   char *ptr;
  159.  
  160.   size = packet->size;
  161.   ptr = &packet->buf[packet->start];
  162.  
  163.   n = write(fd, ptr, size);
  164.   if (n == -1)
  165.     if (errno == EAGAIN || errno == EINTR) return 2;
  166.     else { perror("write_packet "); return -1; }
  167.   if (n == 0) return 2;        /* O_NDELAY hack */
  168.  
  169.   packet->size -= n;
  170.   if (n == size) return 1;
  171.  
  172.     /* didn't write all of the packet */
  173.   packet->start += n;
  174.  
  175.   return 0;
  176. }
  177.  
  178.     /* My own blocking read.
  179.      * read() may not read all requested bytes if:
  180.      *   Get an interrupt the blocking read may not complete.
  181.      *   Nonblocking is turned on.
  182.      */
  183. static int force_read(fd, buf, z) char *buf;
  184. {
  185.   int n;
  186.  
  187.   while (TRUE)
  188.   {
  189.     n = read(fd, buf, z);
  190.     if (n == z)  return TRUE;
  191.     if (n == -1)
  192.     {
  193.       if (errno == EINTR) continue;     /* interrupted system call */
  194.       return FALSE;
  195.     }
  196.     if (n ==  0) return FALSE;
  197.  /* sleep(1);     /*!!!!???? */
  198.     z -= n; buf += n;
  199.   }
  200. }
  201.  
  202. int CSread_packet(packet, fd, pak) CSPacket *packet; int fd; xPacket *pak;
  203. {
  204.   char buf[10];
  205.   int size;
  206.  
  207.     /* read the magic number and packet length */
  208. #if 0
  209.   n = read(fd, buf, 2);
  210.   if (n == -1) { perror("read_packet magic"); return FALSE; }
  211.   if (n != 2) { printf("read_packet didn't read all of header: %d\n", n); return FALSE; }
  212.   if (buf[0] != CS_MAGIC)
  213.     { printf("CSread_packet:  protocal error.\n"); return FALSE; }
  214.  
  215.   size = ((unsigned char *)buf)[1];
  216.   n = read(fd, packet->buf, size);    /* this better block */
  217.   if (n == -1) { perror("read_packet"); return FALSE; }
  218.   if (n != size) { printf("read_packet didn't read all data: %d %d\n", n,size); return FALSE; }
  219. #else
  220.   if (!force_read(fd, buf, 2))
  221.     { printf("read_packet failed on header\n"); return FALSE; }
  222.  
  223.   if (buf[0] != CS_MAGIC)
  224.     { printf("CSread_packet:  protocal error.\n"); return FALSE; }
  225.  
  226.   size = ((unsigned char *)buf)[1];
  227.   if (!force_read(fd, packet->buf, size))
  228.     { printf("read_packet failed reading data\n"); return FALSE; }
  229. #endif
  230.  
  231.   packet->start = 0;
  232.  
  233.   dig_out(packet, "b", &pak->type);
  234.  
  235.   switch(pak->type)
  236.   {
  237.     default:            /* invalid type */
  238.       return FALSE;
  239.  
  240. /********************** To Server ********************************/
  241.     case CS_DIR:        /* (directory path) */
  242.       dig_out(packet, "s", &pak->u.Directory.dir);
  243.       break;
  244.     case CS_COMMAND:        /* (command command-name) */
  245.       dig_out(packet, "s", &pak->u.Command.command);
  246.       break;
  247.     case CS_SIGNAL:        /* (signal pid signal#) */
  248.       dig_out(packet, "nn", &pak->u.Signal.pid, &pak->u.Signal.sig);
  249.       break;
  250.     case CS_CREATE_PROCESS:    /* (create-process two-pipe) */
  251.       dig_out(packet, "n", &pak->u.Process.two_pipe);
  252.       break;
  253.     case CS_DISCONNECT:        /* (disconnect) */
  254.     case CS_DO_IT:        /* (do-it) */
  255.       break;
  256.  
  257. /******************** To Client *********************************/
  258.     case CS_ERROR:        /* (error pid error#) */
  259.       dig_out(packet, "nn", &pak->u.Error.pid, &pak->u.Error.error_code);
  260.       break;
  261.     case CS_PROCESS_ID:
  262.       dig_out(packet, "n", &pak->u.Pid.pid);
  263.       break;
  264.     case CS_PROCESS_DONE:    /* pid,  exit_code */
  265.       dig_out(packet, "nn",
  266.         &pak->u.ProcessDone.pid, &pak->u.ProcessDone.exit_code);
  267.       break;
  268.     case CS_OUTPUT:        /* pid string */
  269.     case CS_OUTPUT_ERR:        /* pid string */
  270.       dig_out(packet, "ns", &pak->u.Output.pid, &pak->u.Output.text);
  271.       break;
  272.  
  273. /******************** To Both *********************************/
  274.     case CS_CLIENT_MSG:
  275.       dig_out(packet, "ns", &pak->u.ClientMsg.tag, &pak->u.ClientMsg.msg);
  276.       pak->u.ClientMsg.dud = 0;
  277.       break;
  278.   }
  279.  
  280.   return TRUE;
  281. }
  282.