home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char *RCSid = "$Header: /source/users/msg/msg/RCS/remote.c,v 1.5 91/08/13 23:59:09 jmsellens Exp $";
- #endif
-
- /* remote.c
- Deliver a message to a user on a remote machine using TCP/IP.
- */
-
- #include "msg.h"
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <arpa/inet.h>
-
- char *syserr();
-
- private int sock = -1; /* the socket */
- private struct sockaddr_in sin;
-
-
- private struct hostent *
- find_host( desthost )
- char *desthost;
- {
- /* stolen from finger */
- static struct hostent def;
- static struct in_addr defaddr;
- static char *alist[1];
- static char namebuf[128];
- struct hostent *hp;
-
- hp = gethostbyname(desthost);
- if (hp == NULL) {
- defaddr.s_addr = inet_addr(desthost);
- if (defaddr.s_addr == -1)
- return( (struct hostent *)NULL );
- strcpy(namebuf, desthost);
- def.h_name = namebuf;
- #ifdef h_addr
- /* older things don't have this field. Newer ones #define h_addr */
- def.h_addr_list = alist;
- #endif
- def.h_addr = (char *)&defaddr;
- def.h_length = sizeof (struct in_addr);
- def.h_addrtype = AF_INET;
- def.h_aliases = 0;
- hp = &def;
- }
- return( hp );
- }
-
-
- private int
- start_remote( desthost )
- char *desthost;
- {
- static struct servent *sp = NULL;
- struct hostent *hp;
- char buf[BUFSIZ];
- version ver;
- int errcode, i;
-
- if (sp == NULL)
- sp = getservbyname( "msg", "tcp" );
- if (sp == NULL)
- fatal( "msg/tcp not defined in services file" );
- hp = find_host( desthost );
- if (hp == NULL) {
- errmsg( BAD_HOST, desthost );
- return( BAD_HOST );
- }
- bzero( (char *)&sin, sizeof(sin) );
- bcopy( hp->h_addr, (char *)&sin.sin_addr, hp->h_length );
- sin.sin_family = hp->h_addrtype;
- sin.sin_port = sp->s_port;
- sock = socket( hp->h_addrtype, SOCK_STREAM, 0 );
- if (sock < 0)
- fatal( "couldn't create socket: %s", syserr() );
- if (connect( sock, (char *)&sin, sizeof(sin) ) < 0) {
- errmsg( NO_CONNECT, desthost, syserr() );
- (void) close(sock);
- sock = -1;
- return( NO_CONNECT );
- }
- /* Now make sure we have a compatible version */
- ver.v.zero = htonl(0);
- ver.v.vnum = htonl(VERSION);
- if ( write( sock, &ver, sizeof(ver) ) < 0 )
- return( REMOTE_WRITE );
- errcode = readint( &i );
- if ( errcode == OK )
- errcode = i;
- if ( errcode == VERSION_OK ) {
- errcode = OK;
- } else if ( errcode == ERROR_MESSAGE ) {
- int code = readint( &i );
- if ( code == OK ) {
- code = read( sock, buf, i );
- if ( code == -1 ) {
- errcode = REMOTE_READ;
- } else {
- buf[i] = '\0';
- errprintf( buf );
- }
- } else
- errcode = code;
- }
- return( errcode );
- }
-
-
- private
- stop_remote()
- {
- if ( sock >= 0 ) {
- (void) close( sock );
- sock = -1;
- }
- }
-
-
- int
- remote( sender, user, desthost, message )
- char *sender, *user, *desthost, *message;
- {
- char buf[BUFSIZ];
- int errcode;
- if ( (errcode = start_remote( desthost )) == OK ) {
- int writeerr = 0;
- header h;
- h.slen = htonl(strlen(sender));
- h.ulen = htonl(strlen(user));
- h.mlen = htonl(strlen(message));
- if ( write( sock, (char *)&h, sizeof(h) ) < 0 ) writeerr++;
- if ( write( sock, sender, strlen(sender) ) < 0 ) writeerr++;
- if ( write( sock, user, strlen(user) ) < 0 ) writeerr++;
- if ( write( sock, message, strlen(message) ) < 0 ) writeerr++;
- if ( writeerr ) {
- errcode = REMOTE_WRITE;
- } else {
- do {
- int i;
- errcode = readint( &i );
- if ( errcode == OK ) errcode = i;
- if ( errcode == ERROR_MESSAGE ) {
- int code = readint( &i );
- if ( code == OK ) {
- code = read( sock, buf, i );
- if ( code == -1 ) {
- errcode = REMOTE_READ;
- } else {
- buf[i] = '\0';
- errprintf( buf );
- }
- } else
- errcode = code;
- }
- } while ( errcode == ERROR_MESSAGE );
- }
- }
- switch ( errcode ) {
- case REMOTE_READ:
- case REMOTE_WRITE:
- errmsg( errcode, desthost, syserr() );
- break;
- case NO_ACK:
- errmsg( errcode, desthost );
- break;
- default: /* do nothing - got message back from remote */
- break;
- }
- stop_remote(); /* hope close doesn't change errno */
- return( errcode );
- }
-
-
- int
- readint(np)
- int *np;
- {
- int n;
-
- switch (read(sock, &n, sizeof n)) {
- case 0:
- return( NO_ACK );
- case sizeof(n):
- *np = ntohl(n);
- return( OK );
- case -1:
- default: /* for incomplete data */
- return( REMOTE_READ );
- }
- /* NOTREACHED */
- }
-