home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / msgd / msg / remote.c < prev   
Encoding:
C/C++ Source or Header  |  1992-03-09  |  4.3 KB  |  196 lines

  1. #ifndef lint
  2. static char *RCSid = "$Header: /source/users/msg/msg/RCS/remote.c,v 1.5 91/08/13 23:59:09 jmsellens Exp $";
  3. #endif
  4.  
  5. /* remote.c
  6.    Deliver a message to a user on a remote machine using TCP/IP.
  7. */
  8.  
  9. #include "msg.h"
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <netdb.h>
  14. #include <arpa/inet.h>
  15.  
  16. char *syserr();
  17.  
  18. private    int            sock = -1;    /* the socket */
  19. private    struct sockaddr_in    sin;
  20.  
  21.  
  22. private struct hostent *
  23. find_host( desthost )
  24. char *desthost;
  25. {
  26.     /* stolen from finger */
  27.     static struct hostent def;
  28.     static struct in_addr defaddr;
  29.     static char *alist[1];
  30.     static char namebuf[128];
  31.     struct hostent *hp;
  32.  
  33.     hp = gethostbyname(desthost);
  34.     if (hp == NULL) {
  35.     defaddr.s_addr = inet_addr(desthost);
  36.     if (defaddr.s_addr == -1)
  37.         return( (struct hostent *)NULL );
  38.     strcpy(namebuf, desthost);
  39.     def.h_name = namebuf;
  40. #ifdef h_addr
  41.     /* older things don't have this field.  Newer ones #define h_addr */
  42.     def.h_addr_list = alist;
  43. #endif
  44.     def.h_addr = (char *)&defaddr;
  45.     def.h_length = sizeof (struct in_addr);
  46.     def.h_addrtype = AF_INET;
  47.     def.h_aliases = 0;
  48.     hp = &def;
  49.     }
  50.     return( hp );
  51. }
  52.  
  53.  
  54. private int
  55. start_remote( desthost )
  56. char *desthost;
  57. {
  58.     static struct servent *sp = NULL;
  59.     struct hostent *hp;
  60.     char buf[BUFSIZ];
  61.     version ver;
  62.     int errcode, i;
  63.  
  64.     if (sp == NULL)
  65.         sp = getservbyname( "msg", "tcp" );
  66.     if (sp == NULL)
  67.     fatal( "msg/tcp not defined in services file" );
  68.     hp = find_host( desthost );
  69.     if (hp == NULL) {
  70.     errmsg( BAD_HOST, desthost );
  71.     return( BAD_HOST );
  72.     }
  73.     bzero( (char *)&sin, sizeof(sin) );
  74.     bcopy( hp->h_addr, (char *)&sin.sin_addr, hp->h_length );
  75.     sin.sin_family    = hp->h_addrtype;
  76.     sin.sin_port    = sp->s_port;
  77.     sock = socket( hp->h_addrtype, SOCK_STREAM, 0 );
  78.     if (sock < 0)
  79.     fatal( "couldn't create socket: %s", syserr() );
  80.     if (connect( sock, (char *)&sin, sizeof(sin) ) < 0) {
  81.     errmsg( NO_CONNECT, desthost, syserr() );
  82.     (void) close(sock);
  83.     sock = -1;
  84.     return( NO_CONNECT );
  85.     }
  86.     /* Now make sure we have a compatible version */
  87.     ver.v.zero = htonl(0);
  88.     ver.v.vnum = htonl(VERSION);
  89.     if ( write( sock, &ver, sizeof(ver) ) < 0 )
  90.     return( REMOTE_WRITE );
  91.     errcode = readint( &i );
  92.     if ( errcode == OK )
  93.     errcode = i;
  94.     if ( errcode == VERSION_OK ) {
  95.     errcode = OK;
  96.     } else if ( errcode == ERROR_MESSAGE ) {
  97.     int code = readint( &i );
  98.     if ( code == OK ) {
  99.         code = read( sock, buf, i );
  100.         if ( code == -1 ) {
  101.         errcode = REMOTE_READ;
  102.         } else {
  103.         buf[i] = '\0';
  104.         errprintf( buf );
  105.         }
  106.     } else
  107.         errcode = code;
  108.     }
  109.     return( errcode );
  110. }
  111.  
  112.  
  113. private
  114. stop_remote()
  115. {
  116.     if ( sock >= 0 ) {
  117.     (void) close( sock );
  118.     sock = -1;
  119.     }
  120. }
  121.  
  122.  
  123. int
  124. remote( sender, user, desthost, message )
  125. char *sender, *user, *desthost, *message;
  126. {
  127.     char buf[BUFSIZ];
  128.     int errcode;
  129.     if ( (errcode = start_remote( desthost )) == OK ) {
  130.     int writeerr = 0;
  131.     header h;
  132.     h.slen = htonl(strlen(sender));
  133.     h.ulen = htonl(strlen(user));
  134.     h.mlen = htonl(strlen(message));
  135.     if ( write( sock, (char *)&h, sizeof(h) ) < 0 ) writeerr++;
  136.     if ( write( sock, sender, strlen(sender) ) < 0 ) writeerr++;
  137.     if ( write( sock, user, strlen(user) ) < 0 ) writeerr++;
  138.     if ( write( sock, message, strlen(message) ) < 0 ) writeerr++;
  139.     if ( writeerr ) {
  140.         errcode = REMOTE_WRITE;
  141.     } else {
  142.         do {
  143.         int i;
  144.         errcode = readint( &i );
  145.         if ( errcode == OK ) errcode = i;
  146.         if ( errcode == ERROR_MESSAGE ) {
  147.             int code = readint( &i );
  148.             if ( code == OK ) {
  149.             code = read( sock, buf, i );
  150.             if ( code == -1 ) {
  151.                 errcode = REMOTE_READ;
  152.             } else {
  153.                 buf[i] = '\0';
  154.                 errprintf( buf );
  155.             }
  156.             } else
  157.             errcode = code;
  158.         }
  159.         } while ( errcode == ERROR_MESSAGE );
  160.     }
  161.     }
  162.     switch ( errcode ) {
  163.     case REMOTE_READ:
  164.     case REMOTE_WRITE:
  165.         errmsg( errcode, desthost, syserr() );
  166.         break;
  167.     case NO_ACK:
  168.         errmsg( errcode, desthost );
  169.         break;
  170.     default:    /* do nothing - got message back from remote */
  171.         break;
  172.     }
  173.     stop_remote(); /* hope close doesn't change errno */
  174.     return( errcode );
  175. }
  176.  
  177.  
  178. int
  179. readint(np)
  180. int *np;
  181. {
  182.     int n;
  183.  
  184.     switch (read(sock, &n, sizeof n)) {
  185.     case 0:
  186.         return( NO_ACK );
  187.     case sizeof(n):
  188.         *np = ntohl(n);
  189.         return( OK );
  190.     case -1:
  191.     default:    /* for incomplete data */
  192.         return( REMOTE_READ );
  193.     }
  194.     /* NOTREACHED */
  195. }
  196.